<commit_before>#include "pythonNeuroProofPriorityInterface.h"
#include "Utilities/ErrMsg.h"
#include "Priority/LocalEdgePriority.h"
#include "ImportsExports/ImportExportRagPriority.h"
#include <json/json.h>
#include <json/value.h>
#include <vector>

#include <fstream>
#include <boost/python.hpp>
//#include <Python.h>

using namespace NeuroProof;
using namespace boost::python;
using std::ifstream; using std::ofstream; using std::cout; using std::endl;
using std::vector;

static LocalEdgePriority<Label>* priority_scheduler = 0;
Rag<Label>* rag = 0;
bool DebugMode = false;

// false if file does not exist or json is not properly formatted
// exception thrown if min, max, or start val are illegal
bool initialize_priority_scheduler(const char * json_file, double min_val, double max_val, double start_val)
{
    if ((min_val < 0) || (max_val > 1.0) || (min_val > max_val) || (start_val > max_val) || (start_val < min_val) ) {
        throw ErrMsg("Priority scheduler filter bounds not properly set");
    }
    if (!priority_scheduler) {
        delete priority_scheduler;
    }

    ifstream fin(json_file);
    Json::Reader json_reader;
    Json::Value json_vals;
    if (!json_reader.parse(fin, json_vals)) {
        throw ErrMsg("Error: Json incorrectly formatted");
    }
    fin.close();

    rag = create_rag_from_json(json_vals);
    if (!rag) {
        return false;
    }

    priority_scheduler = new LocalEdgePriority<Label>(*rag, min_val, max_val, start_val, json_vals);
    //priority_scheduler->updatePriority();

    return true;
}

// false if file cannot be written
bool export_priority_scheduler(const char * json_file)
{
    if (!priority_scheduler) {
        throw ErrMsg("Scheduler not initialized");
    }

    try {
        Json::Value json_writer;
        ofstream fout(json_file);
        if (!fout) {
            throw ErrMsg("Error: output file could not be opened");
        }

        bool status = create_json_from_rag(rag, json_writer, DebugMode);
        if (!status) {
            throw ErrMsg("Error in rag export");
        }

        priority_scheduler->export_json(json_writer);

        fout << json_writer;
        fout.close();
    } catch (ErrMsg& msg) {
        cout << msg.str << endl;
        return false;
    }

    return true;
}

double get_average_prediction_error()
{
    return 0.0;
}

double get_percent_prediction_correct()
{
    return 0.0;
}

// number of edges yet to be processed in the scheduler
unsigned int get_estimated_num_remaining_edges()
{
    if (!priority_scheduler) {
        throw ErrMsg("Scheduler not initialized");
    }

    return priority_scheduler->getNumRemaining();
}

void set_debug_mode()
{
    if (!priority_scheduler) {
        throw ErrMsg("Scheduler not initialized");
    }
    DebugMode = true;
    priority_scheduler->set_debug_mode();
}

void set_synapse_mode(double ignore_size)
{
    if (!priority_scheduler) {
        throw ErrMsg("Scheduler not initialized");
    }

    priority_scheduler->set_synapse_mode(ignore_size);
}

void set_body_mode(double ignore_size, int depth)
{
    if (!priority_scheduler) {
        throw ErrMsg("Scheduler not initialized");
    }

    priority_scheduler->set_body_mode(ignore_size, depth);
}

void set_orphan_mode(double ignore_size, double threshold, bool synapse_orphan)
{
    if (!priority_scheduler) {
        throw ErrMsg("Scheduler not initialized");
    }

    priority_scheduler->set_orphan_mode(ignore_size, threshold, synapse_orphan);
}

void set_edge_mode(double lower, double upper, double start)
{
    if (!priority_scheduler) {
        throw ErrMsg("Scheduler not initialized");
    }

    priority_scheduler->set_edge_mode(lower, upper, start);
}

void estimate_work()
{
    if (DebugMode) {
        return;
    }
    if (!priority_scheduler) {
        throw ErrMsg("Scheduler not initialized");
    }

    priority_scheduler->estimateWork();
}

// empty PriorityInfo if no more edges
PriorityInfo get_next_edge()
{
    PriorityInfo priority_info;
    if (!priority_scheduler) {
        throw ErrMsg("Scheduler not initialized");
    }

    if (priority_scheduler->isFinished()) {
        return priority_info;
    }
    boost::tuple<unsigned int, unsigned int, unsigned int> location;
    boost::tuple<Label, Label> body_pair = priority_scheduler->getTopEdge(location);

    priority_info.body_pair = make_tuple(boost::get<0>(body_pair), boost::get<1>(body_pair));
    priority_info.location = make_tuple(boost::get<0>(location), boost::get<1>(location), boost::get<2>(location));
    return priority_info;
}

double get_edge_val(PriorityInfo priority_info)
{
    if (!priority_scheduler) {
        throw ErrMsg("Scheduler not initialized");
    }

    Label l1 = extract<Label>(priority_info.body_pair[0]);
    Label l2 = extract<Label>(priority_info.body_pair[1]);

    RagEdge<Label>* edge = rag->find_rag_edge(l1, l2);

    if (!edge) {
        throw ErrMsg("Edge not found");
    }
    return edge->get_weight();
}

boost::python::list get_qa_violators(unsigned int threshold)
{
    if (DebugMode) {
        boost::python::list violators_np;
        return violators_np;
    }
    PriorityInfo priority_info;
    if (!priority_scheduler) {
        throw ErrMsg("Scheduler not initialized");
    }

    vector<Label> violators = priority_scheduler->getQAViolators(threshold);

    boost::python::list violators_np;

    for (unsigned int i = 0; i < violators.size(); ++i) {
        violators_np.append(violators[i]);
    }

    return violators_np;
}

// exception throw if edge does not exist or connection probability specified is illegal
void set_edge_result(tuple body_pair, bool remove)
{
    if (!priority_scheduler) {
        throw ErrMsg("Scheduler not initialized");
    }

    Label l1 = extract<Label>(body_pair[0]);
    Label l2 = extract<Label>(body_pair[1]);
    boost::tuple<Label, Label> body_pair_temp(l1, l2);
    priority_scheduler->removeEdge(body_pair_temp, remove);
}

bool undo()
{
    if (!priority_scheduler) {
        throw ErrMsg("Scheduler not initialized");
    }

    return priority_scheduler->undo();
}

BOOST_PYTHON_MODULE(libNeuroProofPriority)
{
    def("initialize_priority_scheduler", initialize_priority_scheduler);
    def("export_priority_scheduler", export_priority_scheduler);
    def("get_next_edge", get_next_edge);
    def("get_qa_violators", get_qa_violators);
    def("set_edge_result", set_edge_result);
    def("undo", undo);
    def("get_percent_prediction_correct", get_percent_prediction_correct);
    def("get_average_prediction_error", get_average_prediction_error);
    def("get_estimated_num_remaining_edges", get_estimated_num_remaining_edges);
    def("set_synapse_mode", set_synapse_mode);
    def("set_debug_mode", set_debug_mode);
    def("set_body_mode", set_body_mode);
    def("set_orphan_mode", set_orphan_mode);
    def("set_edge_mode", set_edge_mode);
    def("get_edge_val", get_edge_val);
    def("estimate_work", estimate_work);

    class_<PriorityInfo>("PriorityInfo")
        .def_readwrite("body_pair", &PriorityInfo::body_pair)
        .def_readonly("location", &PriorityInfo::location);
}

<commit_msg>sets debug mode to false if modes are changed<commit_after>#include "pythonNeuroProofPriorityInterface.h"
#include "Utilities/ErrMsg.h"
#include "Priority/LocalEdgePriority.h"
#include "ImportsExports/ImportExportRagPriority.h"
#include <json/json.h>
#include <json/value.h>
#include <vector>

#include <fstream>
#include <boost/python.hpp>
//#include <Python.h>

using namespace NeuroProof;
using namespace boost::python;
using std::ifstream; using std::ofstream; using std::cout; using std::endl;
using std::vector;

static LocalEdgePriority<Label>* priority_scheduler = 0;
Rag<Label>* rag = 0;
bool DebugMode = false;

// false if file does not exist or json is not properly formatted
// exception thrown if min, max, or start val are illegal
bool initialize_priority_scheduler(const char * json_file, double min_val, double max_val, double start_val)
{
    if ((min_val < 0) || (max_val > 1.0) || (min_val > max_val) || (start_val > max_val) || (start_val < min_val) ) {
        throw ErrMsg("Priority scheduler filter bounds not properly set");
    }
    if (!priority_scheduler) {
        delete priority_scheduler;
    }

    ifstream fin(json_file);
    Json::Reader json_reader;
    Json::Value json_vals;
    if (!json_reader.parse(fin, json_vals)) {
        throw ErrMsg("Error: Json incorrectly formatted");
    }
    fin.close();

    rag = create_rag_from_json(json_vals);
    if (!rag) {
        return false;
    }

    priority_scheduler = new LocalEdgePriority<Label>(*rag, min_val, max_val, start_val, json_vals);
    //priority_scheduler->updatePriority();

    return true;
}

// false if file cannot be written
bool export_priority_scheduler(const char * json_file)
{
    if (!priority_scheduler) {
        throw ErrMsg("Scheduler not initialized");
    }

    try {
        Json::Value json_writer;
        ofstream fout(json_file);
        if (!fout) {
            throw ErrMsg("Error: output file could not be opened");
        }

        bool status = create_json_from_rag(rag, json_writer, DebugMode);
        if (!status) {
            throw ErrMsg("Error in rag export");
        }

        priority_scheduler->export_json(json_writer);

        fout << json_writer;
        fout.close();
    } catch (ErrMsg& msg) {
        cout << msg.str << endl;
        return false;
    }

    return true;
}

double get_average_prediction_error()
{
    return 0.0;
}

double get_percent_prediction_correct()
{
    return 0.0;
}

// number of edges yet to be processed in the scheduler
unsigned int get_estimated_num_remaining_edges()
{
    if (!priority_scheduler) {
        throw ErrMsg("Scheduler not initialized");
    }

    return priority_scheduler->getNumRemaining();
}

void set_debug_mode()
{
    if (!priority_scheduler) {
        throw ErrMsg("Scheduler not initialized");
    }
    DebugMode = true;
    priority_scheduler->set_debug_mode();
}

void set_synapse_mode(double ignore_size)
{
    if (!priority_scheduler) {
        throw ErrMsg("Scheduler not initialized");
    }
    DebugMode = false;

    priority_scheduler->set_synapse_mode(ignore_size);
}

void set_body_mode(double ignore_size, int depth)
{
    if (!priority_scheduler) {
        throw ErrMsg("Scheduler not initialized");
    }
    DebugMode = false;

    priority_scheduler->set_body_mode(ignore_size, depth);
}

void set_orphan_mode(double ignore_size, double threshold, bool synapse_orphan)
{
    if (!priority_scheduler) {
        throw ErrMsg("Scheduler not initialized");
    }
    DebugMode = false;

    priority_scheduler->set_orphan_mode(ignore_size, threshold, synapse_orphan);
}

void set_edge_mode(double lower, double upper, double start)
{
    if (!priority_scheduler) {
        throw ErrMsg("Scheduler not initialized");
    }
    DebugMode = false;

    priority_scheduler->set_edge_mode(lower, upper, start);
}

void estimate_work()
{
    if (DebugMode) {
        return;
    }
    if (!priority_scheduler) {
        throw ErrMsg("Scheduler not initialized");
    }

    priority_scheduler->estimateWork();
}

// empty PriorityInfo if no more edges
PriorityInfo get_next_edge()
{
    PriorityInfo priority_info;
    if (!priority_scheduler) {
        throw ErrMsg("Scheduler not initialized");
    }

    if (priority_scheduler->isFinished()) {
        return priority_info;
    }
    boost::tuple<unsigned int, unsigned int, unsigned int> location;
    boost::tuple<Label, Label> body_pair = priority_scheduler->getTopEdge(location);

    priority_info.body_pair = make_tuple(boost::get<0>(body_pair), boost::get<1>(body_pair));
    priority_info.location = make_tuple(boost::get<0>(location), boost::get<1>(location), boost::get<2>(location));
    return priority_info;
}

double get_edge_val(PriorityInfo priority_info)
{
    if (!priority_scheduler) {
        throw ErrMsg("Scheduler not initialized");
    }

    Label l1 = extract<Label>(priority_info.body_pair[0]);
    Label l2 = extract<Label>(priority_info.body_pair[1]);

    RagEdge<Label>* edge = rag->find_rag_edge(l1, l2);

    if (!edge) {
        throw ErrMsg("Edge not found");
    }
    return edge->get_weight();
}

boost::python::list get_qa_violators(unsigned int threshold)
{
    if (DebugMode) {
        boost::python::list violators_np;
        return violators_np;
    }
    PriorityInfo priority_info;
    if (!priority_scheduler) {
        throw ErrMsg("Scheduler not initialized");
    }

    vector<Label> violators = priority_scheduler->getQAViolators(threshold);

    boost::python::list violators_np;

    for (unsigned int i = 0; i < violators.size(); ++i) {
        violators_np.append(violators[i]);
    }

    return violators_np;
}

// exception throw if edge does not exist or connection probability specified is illegal
void set_edge_result(tuple body_pair, bool remove)
{
    if (!priority_scheduler) {
        throw ErrMsg("Scheduler not initialized");
    }

    Label l1 = extract<Label>(body_pair[0]);
    Label l2 = extract<Label>(body_pair[1]);
    boost::tuple<Label, Label> body_pair_temp(l1, l2);
    priority_scheduler->removeEdge(body_pair_temp, remove);
}

bool undo()
{
    if (!priority_scheduler) {
        throw ErrMsg("Scheduler not initialized");
    }

    return priority_scheduler->undo();
}

BOOST_PYTHON_MODULE(libNeuroProofPriority)
{
    def("initialize_priority_scheduler", initialize_priority_scheduler);
    def("export_priority_scheduler", export_priority_scheduler);
    def("get_next_edge", get_next_edge);
    def("get_qa_violators", get_qa_violators);
    def("set_edge_result", set_edge_result);
    def("undo", undo);
    def("get_percent_prediction_correct", get_percent_prediction_correct);
    def("get_average_prediction_error", get_average_prediction_error);
    def("get_estimated_num_remaining_edges", get_estimated_num_remaining_edges);
    def("set_synapse_mode", set_synapse_mode);
    def("set_debug_mode", set_debug_mode);
    def("set_body_mode", set_body_mode);
    def("set_orphan_mode", set_orphan_mode);
    def("set_edge_mode", set_edge_mode);
    def("get_edge_val", get_edge_val);
    def("estimate_work", estimate_work);

    class_<PriorityInfo>("PriorityInfo")
        .def_readwrite("body_pair", &PriorityInfo::body_pair)
        .def_readonly("location", &PriorityInfo::location);
}

<|endoftext|>


<commit_before>#include "parser.h"

#include <unordered_map>

#include "ast.h"
#include "file.h"
#include "loc.h"
#include "log.h"
#include "string_piece.h"
#include "value.h"

enum struct ParserState {
  NOT_AFTER_RULE = 0,
  AFTER_RULE,
  MAYBE_AFTER_RULE,
};

class Parser {
 public:
  Parser(StringPiece buf, const char* filename, vector<AST*>* asts)
      : buf_(buf),
        state_(ParserState::NOT_AFTER_RULE),
        out_asts_(asts),
        loc_(filename, 0),
        fixed_lineno_(false) {
  }

  ~Parser() {
  }

  void Parse() {
    l_ = 0;

    for (l_ = 0; l_ < buf_.size();) {
      size_t lf_cnt = 0;
      size_t e = FindEndOfLine(&lf_cnt);
      if (!fixed_lineno_)
        loc_.lineno += lf_cnt;
      StringPiece line(buf_.data() + l_, e - l_);
      ParseLine(line);
      if (e == buf_.size())
        break;

      l_ = e + 1;
    }
  }

  static void Init() {
    make_directives_ = new unordered_map<StringPiece, DirectiveHandler>;
    (*make_directives_)["include"] = &Parser::ParseIncludeAST;
    (*make_directives_)["-include"] = &Parser::ParseIncludeAST;
    (*make_directives_)["sinclude"] = &Parser::ParseIncludeAST;

    shortest_directive_len_ = 9999;
    longest_directive_len_ = 0;
    for (auto p : *make_directives_) {
      size_t len = p.first.size();
      shortest_directive_len_ = min(len, shortest_directive_len_);
      longest_directive_len_ = max(len, longest_directive_len_);
    }
  }

  static void Quit() {
    delete make_directives_;
  }

 private:
  void Error(const string& msg) {
    ERROR("%s:%d: %s", LOCF(loc_), msg.c_str());
  }

  size_t FindEndOfLine(size_t* lf_cnt) {
    size_t e = l_;
    bool prev_backslash = false;
    for (; e < buf_.size(); e++) {
      char c = buf_[e];
      if (c == '\\') {
        prev_backslash = !prev_backslash;
      } else if (c == '\n') {
        ++*lf_cnt;
        if (!prev_backslash) {
          return e;
        }
      } else if (c != '\r') {
        prev_backslash = false;
      }
    }
    return e;
  }

  void ParseLine(StringPiece line) {
    if (line.empty() || (line.size() == 1 && line[0] == '\r'))
      return;

    if (line[0] == '\t' && state_ != ParserState::NOT_AFTER_RULE) {
      CommandAST* ast = new CommandAST();
      ast->expr = ParseExpr(line.substr(1), true);
      out_asts_->push_back(ast);
      return;
    }

    line = line.StripLeftSpaces();
    if (HandleDirective(line)) {
      return;
    }

    size_t sep = line.find_first_of(STRING_PIECE("=:"));
    if (sep == string::npos) {
      ParseRuleAST(line, sep);
    } else if (line[sep] == '=') {
      ParseAssignAST(line, sep);
    } else if (line.get(sep+1) == '=') {
      ParseAssignAST(line, sep+1);
    } else if (line[sep] == ':') {
      ParseRuleAST(line, sep);
    } else {
      CHECK(false);
    }
  }

  void ParseRuleAST(StringPiece line, size_t sep) {
    const bool is_rule = line.find(':') != string::npos;
    RuleAST* ast = new RuleAST;
    ast->set_loc(loc_);

    size_t found = line.substr(sep + 1).find_first_of("=;");
    if (found != string::npos) {
      found += sep + 1;
      ast->term = line[found];
      ast->after_term = ParseExpr(line.substr(found + 1).StripLeftSpaces(),
                                  ast->term == ';');
      ast->expr = ParseExpr(line.substr(0, found).StripSpaces(), false);
    } else {
      ast->term = 0;
      ast->after_term = NULL;
      ast->expr = ParseExpr(line.StripSpaces(), false);
    }
    out_asts_->push_back(ast);
    state_ = is_rule ? ParserState::AFTER_RULE : ParserState::MAYBE_AFTER_RULE;
  }

  void ParseAssignAST(StringPiece line, size_t sep) {
    if (sep == 0)
      Error("*** empty variable name ***");
    AssignOp op = AssignOp::EQ;
    size_t lhs_end = sep;
    switch (line[sep-1]) {
      case ':':
        lhs_end--;
        op = AssignOp::COLON_EQ;
        break;
      case '+':
        lhs_end--;
        op = AssignOp::PLUS_EQ;
        break;
      case '?':
        lhs_end--;
        op = AssignOp::QUESTION_EQ;
        break;
    }

    AssignAST* ast = new AssignAST;
    ast->set_loc(loc_);
    ast->lhs = ParseExpr(line.substr(0, lhs_end).StripSpaces(), false);
    ast->rhs = ParseExpr(line.substr(sep + 1).StripLeftSpaces(), false);
    ast->op = op;
    ast->directive = AssignDirective::NONE;
    out_asts_->push_back(ast);
    state_ = ParserState::NOT_AFTER_RULE;
  }

  void ParseIncludeAST(StringPiece line, StringPiece directive) {
    IncludeAST* ast = new IncludeAST();
    ast->expr = ParseExpr(line, false);
    ast->should_exist = directive[0] == 'i';
    out_asts_->push_back(ast);
  }

  bool HandleDirective(StringPiece line) {
    if (line.size() < shortest_directive_len_)
      return false;
    StringPiece prefix = line.substr(0, longest_directive_len_ + 1);
    size_t space_index = prefix.find(' ');
    if (space_index == string::npos)
      return false;
    StringPiece directive = prefix.substr(0, space_index);
    auto found = make_directives_->find(directive);
    if (found == make_directives_->end())
      return false;

    (this->*found->second)(line.substr(directive.size() + 1), directive);
    return true;
  }

  StringPiece buf_;
  size_t l_;
  ParserState state_;

  vector<AST*>* out_asts_;

  Loc loc_;
  bool fixed_lineno_;

  typedef void (Parser::*DirectiveHandler)(
      StringPiece line, StringPiece directive);
  static unordered_map<StringPiece, DirectiveHandler>* make_directives_;
  static size_t shortest_directive_len_;
  static size_t longest_directive_len_;
};

void Parse(Makefile* mk) {
  Parser parser(StringPiece(mk->buf(), mk->len()),
                mk->filename().c_str(),
                mk->mutable_asts());
  parser.Parse();
}

void InitParser() {
  Parser::Init();
}

void QuitParser() {
  Parser::Quit();
}

unordered_map<StringPiece, Parser::DirectiveHandler>* Parser::make_directives_;
size_t Parser::shortest_directive_len_;
size_t Parser::longest_directive_len_;
<commit_msg>[C++] Remove AST suffixes from Parser::ParseXXX<commit_after>#include "parser.h"

#include <unordered_map>

#include "ast.h"
#include "file.h"
#include "loc.h"
#include "log.h"
#include "string_piece.h"
#include "value.h"

enum struct ParserState {
  NOT_AFTER_RULE = 0,
  AFTER_RULE,
  MAYBE_AFTER_RULE,
};

class Parser {
 public:
  Parser(StringPiece buf, const char* filename, vector<AST*>* asts)
      : buf_(buf),
        state_(ParserState::NOT_AFTER_RULE),
        out_asts_(asts),
        loc_(filename, 0),
        fixed_lineno_(false) {
  }

  ~Parser() {
  }

  void Parse() {
    l_ = 0;

    for (l_ = 0; l_ < buf_.size();) {
      size_t lf_cnt = 0;
      size_t e = FindEndOfLine(&lf_cnt);
      if (!fixed_lineno_)
        loc_.lineno += lf_cnt;
      StringPiece line(buf_.data() + l_, e - l_);
      ParseLine(line);
      if (e == buf_.size())
        break;

      l_ = e + 1;
    }
  }

  static void Init() {
    make_directives_ = new unordered_map<StringPiece, DirectiveHandler>;
    (*make_directives_)["include"] = &Parser::ParseInclude;
    (*make_directives_)["-include"] = &Parser::ParseInclude;
    (*make_directives_)["sinclude"] = &Parser::ParseInclude;

    shortest_directive_len_ = 9999;
    longest_directive_len_ = 0;
    for (auto p : *make_directives_) {
      size_t len = p.first.size();
      shortest_directive_len_ = min(len, shortest_directive_len_);
      longest_directive_len_ = max(len, longest_directive_len_);
    }
  }

  static void Quit() {
    delete make_directives_;
  }

 private:
  void Error(const string& msg) {
    ERROR("%s:%d: %s", LOCF(loc_), msg.c_str());
  }

  size_t FindEndOfLine(size_t* lf_cnt) {
    size_t e = l_;
    bool prev_backslash = false;
    for (; e < buf_.size(); e++) {
      char c = buf_[e];
      if (c == '\\') {
        prev_backslash = !prev_backslash;
      } else if (c == '\n') {
        ++*lf_cnt;
        if (!prev_backslash) {
          return e;
        }
      } else if (c != '\r') {
        prev_backslash = false;
      }
    }
    return e;
  }

  void ParseLine(StringPiece line) {
    if (line.empty() || (line.size() == 1 && line[0] == '\r'))
      return;

    if (line[0] == '\t' && state_ != ParserState::NOT_AFTER_RULE) {
      CommandAST* ast = new CommandAST();
      ast->expr = ParseExpr(line.substr(1), true);
      out_asts_->push_back(ast);
      return;
    }

    line = line.StripLeftSpaces();
    if (HandleDirective(line)) {
      return;
    }

    size_t sep = line.find_first_of(STRING_PIECE("=:"));
    if (sep == string::npos) {
      ParseRule(line, sep);
    } else if (line[sep] == '=') {
      ParseAssign(line, sep);
    } else if (line.get(sep+1) == '=') {
      ParseAssign(line, sep+1);
    } else if (line[sep] == ':') {
      ParseRule(line, sep);
    } else {
      CHECK(false);
    }
  }

  void ParseRule(StringPiece line, size_t sep) {
    const bool is_rule = line.find(':') != string::npos;
    RuleAST* ast = new RuleAST;
    ast->set_loc(loc_);

    size_t found = line.substr(sep + 1).find_first_of("=;");
    if (found != string::npos) {
      found += sep + 1;
      ast->term = line[found];
      ast->after_term = ParseExpr(line.substr(found + 1).StripLeftSpaces(),
                                  ast->term == ';');
      ast->expr = ParseExpr(line.substr(0, found).StripSpaces(), false);
    } else {
      ast->term = 0;
      ast->after_term = NULL;
      ast->expr = ParseExpr(line.StripSpaces(), false);
    }
    out_asts_->push_back(ast);
    state_ = is_rule ? ParserState::AFTER_RULE : ParserState::MAYBE_AFTER_RULE;
  }

  void ParseAssign(StringPiece line, size_t sep) {
    if (sep == 0)
      Error("*** empty variable name ***");
    AssignOp op = AssignOp::EQ;
    size_t lhs_end = sep;
    switch (line[sep-1]) {
      case ':':
        lhs_end--;
        op = AssignOp::COLON_EQ;
        break;
      case '+':
        lhs_end--;
        op = AssignOp::PLUS_EQ;
        break;
      case '?':
        lhs_end--;
        op = AssignOp::QUESTION_EQ;
        break;
    }

    AssignAST* ast = new AssignAST;
    ast->set_loc(loc_);
    ast->lhs = ParseExpr(line.substr(0, lhs_end).StripSpaces(), false);
    ast->rhs = ParseExpr(line.substr(sep + 1).StripLeftSpaces(), false);
    ast->op = op;
    ast->directive = AssignDirective::NONE;
    out_asts_->push_back(ast);
    state_ = ParserState::NOT_AFTER_RULE;
  }

  void ParseInclude(StringPiece line, StringPiece directive) {
    IncludeAST* ast = new IncludeAST();
    ast->expr = ParseExpr(line, false);
    ast->should_exist = directive[0] == 'i';
    out_asts_->push_back(ast);
  }

  bool HandleDirective(StringPiece line) {
    if (line.size() < shortest_directive_len_)
      return false;
    StringPiece prefix = line.substr(0, longest_directive_len_ + 1);
    size_t space_index = prefix.find(' ');
    if (space_index == string::npos)
      return false;
    StringPiece directive = prefix.substr(0, space_index);
    auto found = make_directives_->find(directive);
    if (found == make_directives_->end())
      return false;

    (this->*found->second)(line.substr(directive.size() + 1), directive);
    return true;
  }

  StringPiece buf_;
  size_t l_;
  ParserState state_;

  vector<AST*>* out_asts_;

  Loc loc_;
  bool fixed_lineno_;

  typedef void (Parser::*DirectiveHandler)(
      StringPiece line, StringPiece directive);
  static unordered_map<StringPiece, DirectiveHandler>* make_directives_;
  static size_t shortest_directive_len_;
  static size_t longest_directive_len_;
};

void Parse(Makefile* mk) {
  Parser parser(StringPiece(mk->buf(), mk->len()),
                mk->filename().c_str(),
                mk->mutable_asts());
  parser.Parse();
}

void InitParser() {
  Parser::Init();
}

void QuitParser() {
  Parser::Quit();
}

unordered_map<StringPiece, Parser::DirectiveHandler>* Parser::make_directives_;
size_t Parser::shortest_directive_len_;
size_t Parser::longest_directive_len_;
<|endoftext|>


<commit_before>/// @file
/// @author uentity
/// @date 28.06.2018
/// @brief BS tree links serialization code
/// @copyright
/// This Source Code Form is subject to the terms of the Mozilla Public License,
/// v. 2.0. If a copy of the MPL was not distributed with this file,
/// You can obtain one at https://mozilla.org/MPL/2.0/

#include <bs/serialize/serialize.h>
#include <bs/serialize/tree.h>
#include <bs/serialize/boost_uuid.h>

#include "../tree/link_impl.h"
#include "../tree/fusion_link_impl.h"

#include <cereal/types/chrono.hpp>

using namespace cereal;
using namespace blue_sky;
using Req = blue_sky::tree::link::Req;
using ReqStatus = blue_sky::tree::link::ReqStatus;

/*-----------------------------------------------------------------------------
 *  inode
 *-----------------------------------------------------------------------------*/
BSS_FCN_BEGIN(save, tree::inode)
	ar(
		make_nvp("flags", t.flags),
		make_nvp("u", t.u),
		make_nvp("g", t.g),
		make_nvp("o", t.o),
		make_nvp("mod_time", t.mod_time),
		make_nvp("owner", t.owner),
		make_nvp("group", t.group)
	);
BSS_FCN_END

BSS_FCN_BEGIN(load, tree::inode)
	tree::inode::Flags flags;
	ar(make_nvp("flags", flags));
	t.flags = flags;
	std::uint8_t r;
	ar(make_nvp("u", r));
	t.u = r;
	ar(make_nvp("g", r));
	t.g = r;
	ar(make_nvp("o", r));
	t.o = r;
	ar(
		make_nvp("mod_time", t.mod_time),
		make_nvp("owner", t.owner),
		make_nvp("group", t.group)
	);
BSS_FCN_END

BSS_FCN_EXPORT(save, tree::inode)
BSS_FCN_EXPORT(load, tree::inode)

/*-----------------------------------------------------------------------------
 *  link
 *-----------------------------------------------------------------------------*/
BSS_FCN_BEGIN(serialize, tree::link)
	// [NOTE] intentionally DON'T save name,
	// because name will be saved in derived classes to invoke minimal constructor
	// [NOTE] intentionally do net serialize owner, it will be set up when parent node is loaded
	ar(
		make_nvp("id", t.pimpl_->id_),
		make_nvp("flags", t.pimpl_->flags_)
	);
	// assume link is root by default -- it's safe when restoring link or tree from archive
	if constexpr(Archive::is_loading::value)
		t.propagate_handle();
BSS_FCN_END

BSS_FCN_EXPORT(serialize, tree::link)

/*-----------------------------------------------------------------------------
 *  ilink
 *-----------------------------------------------------------------------------*/
BSS_FCN_BEGIN(serialize, tree::ilink)
	// serialize inode
	ar(make_nvp("inode", t.inode_));
	// serialize base link by direct call in order to omit creating inner JSON section
	serialize<tree::link>::go(ar, t, version);
BSS_FCN_END

CEREAL_REGISTER_POLYMORPHIC_RELATION(tree::link, tree::ilink)
BSS_FCN_EXPORT(serialize, tree::ilink)

/*-----------------------------------------------------------------------------
 *  hard_link
 *-----------------------------------------------------------------------------*/
// provide non-empty constructor
BSS_FCN_BEGIN(load_and_construct, tree::hard_link)
	// load name & construct instance
	std::string name;
	ar(name);
	construct(std::move(name), sp_obj{});
	auto plnk = construct.ptr();

	// helper that sets OK status on successfull object deserialization
	static const auto update_status = [](auto& L) {
		L.data_impl().map([&L](const sp_obj& obj) {
			if(!obj) return;
			L.rs_reset(Req::Data, ReqStatus::OK);
			if(obj->is_node())
				L.rs_reset(Req::DataNode, ReqStatus::OK);
		});
	};
	// load data with deferred 2nd trial
	ar( defer_failed(plnk->data_, [plnk](sp_obj obj) {
		plnk->data_ = std::move(obj);
		update_status(*plnk);
	}) );
	// if 1st trial succeeded, update status
	update_status(*plnk);

	// load base link
	ar( base_class<tree::ilink>(plnk) );
BSS_FCN_END

BSS_FCN_BEGIN(serialize, tree::hard_link)
	ar(
		make_nvp("name", t.pimpl_->name_),
		make_nvp("data", t.data_),
		make_nvp("linkbase", base_class<tree::ilink>(&t))
	);
BSS_FCN_END

BSS_FCN_EXPORT(serialize, tree::hard_link)
BSS_FCN_EXPORT(load_and_construct, tree::hard_link)

/*-----------------------------------------------------------------------------
 *  weak_link
 *-----------------------------------------------------------------------------*/
// provide non-empty constructor
BSS_FCN_BEGIN(load_and_construct, tree::weak_link)
	// load name & construct instance
	std::string name;
	ar(name);
	sp_obj data;
	construct(std::move(name), data);
	auto plnk = construct.ptr();

	// helper that sets OK status on successfull object deserialization
	static const auto update_status = [](auto& L) {
		L.data_impl().map([&L](const sp_obj& obj) {
			if(!obj) return;
			L.rs_reset(Req::Data, ReqStatus::OK);
			if(obj->is_node())
				L.rs_reset(Req::DataNode, ReqStatus::OK);
		});
	};
	// load data with deferred 2nd trial
	ar( defer_failed(data, [plnk](const sp_obj& obj) {
		plnk->data_ = obj;
		update_status(*plnk);
	}) );
	// if 1st trial succeeded, update status
	if(data) plnk->data_ = data;
	update_status(*plnk);

	// load base link
	ar( base_class<tree::ilink>(plnk) );
BSS_FCN_END

BSS_FCN_BEGIN(serialize, tree::weak_link)
	ar(
		make_nvp("name", t.pimpl_->name_),
		make_nvp("data", t.data_.lock()),
		make_nvp("linkbase", base_class<tree::ilink>(&t))
	);
BSS_FCN_END

BSS_FCN_EXPORT(serialize, tree::weak_link)
BSS_FCN_EXPORT(load_and_construct, tree::weak_link)

/*-----------------------------------------------------------------------------
 *  sym_link
 *-----------------------------------------------------------------------------*/
// provide non-empty constructor
BSS_FCN_BEGIN(load_and_construct, tree::sym_link)
	// load both name and path & construct instance
	std::string name, path;
	ar(name, path);
	construct(std::move(name), std::move(path));
	auto plnk = construct.ptr();

	// load base link
	ar( base_class<tree::link>(plnk) );
	// defer update symlink Data status
	ar( defer(Functor{ [plnk](auto&) { plnk->check_alive(); } }) );
BSS_FCN_END

BSS_FCN_BEGIN(serialize, tree::sym_link)
	ar(
		make_nvp("name", t.pimpl_->name_),
		make_nvp("path", t.path_),
		make_nvp("linkbase", base_class<tree::link>(&t))
	);
BSS_FCN_END

BSS_FCN_EXPORT(serialize, tree::sym_link)
BSS_FCN_EXPORT(load_and_construct, tree::sym_link)

/*-----------------------------------------------------------------------------
 *  fusion_link
 *-----------------------------------------------------------------------------*/
BSS_FCN_BEGIN(serialize, tree::fusion_link)
	ar(
		make_nvp("name", static_cast<tree::link&>(t).pimpl_->name_),
		make_nvp("bridge", t.pimpl_->bridge_),
		make_nvp("linkbase", base_class<tree::ilink>(&t))
	);
BSS_FCN_END

BSS_FCN_BEGIN(load_and_construct, tree::fusion_link)
	// load name & construct instance
	std::string name;
	ar(name);
	construct(std::move(name), tree::sp_node{}, tree::sp_fusion{});
	auto plnk = construct.ptr();

	// load bridge with deferred trial
	ar( defer_failed(plnk->pimpl_->bridge_) );

	// base link
	ar( base_class<tree::ilink>(plnk) );
BSS_FCN_END

BSS_FCN_EXPORT(serialize, tree::fusion_link)
BSS_FCN_EXPORT(load_and_construct, tree::fusion_link)

/*-----------------------------------------------------------------------------
 *  instantiate code for polymorphic types
 *-----------------------------------------------------------------------------*/
using namespace blue_sky;
//CEREAL_REGISTER_TYPE_WITH_NAME(tree::link, "link")
CEREAL_REGISTER_TYPE_WITH_NAME(tree::hard_link, "hard_link")
CEREAL_REGISTER_TYPE_WITH_NAME(tree::weak_link, "weak_link")
CEREAL_REGISTER_TYPE_WITH_NAME(tree::sym_link, "sym_link")
CEREAL_REGISTER_TYPE_WITH_NAME(tree::fusion_link, "fusion_link")

BSS_REGISTER_DYNAMIC_INIT(link)

<commit_msg>serial/link: reduce code bloat thanks to new flag in `defer_failed()`<commit_after>/// @file
/// @author uentity
/// @date 28.06.2018
/// @brief BS tree links serialization code
/// @copyright
/// This Source Code Form is subject to the terms of the Mozilla Public License,
/// v. 2.0. If a copy of the MPL was not distributed with this file,
/// You can obtain one at https://mozilla.org/MPL/2.0/

#include <bs/serialize/serialize.h>
#include <bs/serialize/tree.h>
#include <bs/serialize/boost_uuid.h>

#include "../tree/link_impl.h"
#include "../tree/fusion_link_impl.h"

#include <cereal/types/chrono.hpp>

using namespace cereal;
using namespace blue_sky;
using Req = blue_sky::tree::link::Req;
using ReqStatus = blue_sky::tree::link::ReqStatus;

/*-----------------------------------------------------------------------------
 *  inode
 *-----------------------------------------------------------------------------*/
BSS_FCN_BEGIN(save, tree::inode)
	ar(
		make_nvp("flags", t.flags),
		make_nvp("u", t.u),
		make_nvp("g", t.g),
		make_nvp("o", t.o),
		make_nvp("mod_time", t.mod_time),
		make_nvp("owner", t.owner),
		make_nvp("group", t.group)
	);
BSS_FCN_END

BSS_FCN_BEGIN(load, tree::inode)
	tree::inode::Flags flags;
	ar(make_nvp("flags", flags));
	t.flags = flags;
	std::uint8_t r;
	ar(make_nvp("u", r));
	t.u = r;
	ar(make_nvp("g", r));
	t.g = r;
	ar(make_nvp("o", r));
	t.o = r;
	ar(
		make_nvp("mod_time", t.mod_time),
		make_nvp("owner", t.owner),
		make_nvp("group", t.group)
	);
BSS_FCN_END

BSS_FCN_EXPORT(save, tree::inode)
BSS_FCN_EXPORT(load, tree::inode)

/*-----------------------------------------------------------------------------
 *  link
 *-----------------------------------------------------------------------------*/
BSS_FCN_BEGIN(serialize, tree::link)
	// [NOTE] intentionally DON'T save name,
	// because name will be saved in derived classes to invoke minimal constructor
	// [NOTE] intentionally do net serialize owner, it will be set up when parent node is loaded
	ar(
		make_nvp("id", t.pimpl_->id_),
		make_nvp("flags", t.pimpl_->flags_)
	);
	// assume link is root by default -- it's safe when restoring link or tree from archive
	if constexpr(Archive::is_loading::value)
		t.propagate_handle();
BSS_FCN_END

BSS_FCN_EXPORT(serialize, tree::link)

/*-----------------------------------------------------------------------------
 *  ilink
 *-----------------------------------------------------------------------------*/
BSS_FCN_BEGIN(serialize, tree::ilink)
	// serialize inode
	ar(make_nvp("inode", t.inode_));
	// serialize base link by direct call in order to omit creating inner JSON section
	serialize<tree::link>::go(ar, t, version);
BSS_FCN_END

CEREAL_REGISTER_POLYMORPHIC_RELATION(tree::link, tree::ilink)
BSS_FCN_EXPORT(serialize, tree::ilink)

/*-----------------------------------------------------------------------------
 *  hard_link
 *-----------------------------------------------------------------------------*/
// provide non-empty constructor
BSS_FCN_BEGIN(load_and_construct, tree::hard_link)
	// load name & construct instance
	std::string name;
	ar(name);
	construct(std::move(name), sp_obj{});
	auto plnk = construct.ptr();

	// initializer that sets OK status on successfull object deserialization
	auto data_init = [plnk](auto obj) {
		if(( plnk->data_ = std::move(obj) )) {
			plnk->rs_reset(Req::Data, ReqStatus::OK);
			if(plnk->data_->is_node())
				plnk->rs_reset(Req::DataNode, ReqStatus::OK);
		}
	};
	// load data with deferred 2nd trial
	ar( defer_failed(plnk->data_, std::move(data_init), PtrInitTrigger::SuccessAndRetry) );
	// load base link
	ar( base_class<tree::ilink>(plnk) );
BSS_FCN_END

BSS_FCN_BEGIN(serialize, tree::hard_link)
	ar(
		make_nvp("name", t.pimpl_->name_),
		make_nvp("data", t.data_),
		make_nvp("linkbase", base_class<tree::ilink>(&t))
	);
BSS_FCN_END

BSS_FCN_EXPORT(serialize, tree::hard_link)
BSS_FCN_EXPORT(load_and_construct, tree::hard_link)

/*-----------------------------------------------------------------------------
 *  weak_link
 *-----------------------------------------------------------------------------*/
// provide non-empty constructor
BSS_FCN_BEGIN(load_and_construct, tree::weak_link)
	// load name & construct instance
	std::string name;
	ar(name);
	sp_obj data;
	construct(std::move(name), data);
	auto plnk = construct.ptr();

	// helper that sets OK status on successfull object deserialization
	auto data_init = [plnk](const sp_obj& obj) {
		plnk->data_ = obj;
		if(obj) {
			plnk->rs_reset(Req::Data, ReqStatus::OK);
			if(obj->is_node())
				plnk->rs_reset(Req::DataNode, ReqStatus::OK);
		}
	};
	// load data with deferred 2nd trial
	ar( defer_failed(data, std::move(data_init), PtrInitTrigger::SuccessAndRetry) );
	// load base link
	ar( base_class<tree::ilink>(plnk) );
BSS_FCN_END

BSS_FCN_BEGIN(serialize, tree::weak_link)
	ar(
		make_nvp("name", t.pimpl_->name_),
		make_nvp("data", t.data_.lock()),
		make_nvp("linkbase", base_class<tree::ilink>(&t))
	);
BSS_FCN_END

BSS_FCN_EXPORT(serialize, tree::weak_link)
BSS_FCN_EXPORT(load_and_construct, tree::weak_link)

/*-----------------------------------------------------------------------------
 *  sym_link
 *-----------------------------------------------------------------------------*/
// provide non-empty constructor
BSS_FCN_BEGIN(load_and_construct, tree::sym_link)
	// load both name and path & construct instance
	std::string name, path;
	ar(name, path);
	construct(std::move(name), std::move(path));
	auto plnk = construct.ptr();

	// load base link
	ar( base_class<tree::link>(plnk) );
	// defer update symlink Data status
	ar( defer(Functor{ [plnk](auto&) { plnk->check_alive(); } }) );
BSS_FCN_END

BSS_FCN_BEGIN(serialize, tree::sym_link)
	ar(
		make_nvp("name", t.pimpl_->name_),
		make_nvp("path", t.path_),
		make_nvp("linkbase", base_class<tree::link>(&t))
	);
BSS_FCN_END

BSS_FCN_EXPORT(serialize, tree::sym_link)
BSS_FCN_EXPORT(load_and_construct, tree::sym_link)

/*-----------------------------------------------------------------------------
 *  fusion_link
 *-----------------------------------------------------------------------------*/
BSS_FCN_BEGIN(serialize, tree::fusion_link)
	ar(
		make_nvp("name", static_cast<tree::link&>(t).pimpl_->name_),
		make_nvp("bridge", t.pimpl_->bridge_),
		make_nvp("linkbase", base_class<tree::ilink>(&t))
	);
BSS_FCN_END

BSS_FCN_BEGIN(load_and_construct, tree::fusion_link)
	// load name & construct instance
	std::string name;
	ar(name);
	construct(std::move(name), tree::sp_node{}, tree::sp_fusion{});
	auto plnk = construct.ptr();

	// load bridge with deferred trial
	ar( defer_failed(plnk->pimpl_->bridge_) );

	// base link
	ar( base_class<tree::ilink>(plnk) );
BSS_FCN_END

BSS_FCN_EXPORT(serialize, tree::fusion_link)
BSS_FCN_EXPORT(load_and_construct, tree::fusion_link)

/*-----------------------------------------------------------------------------
 *  instantiate code for polymorphic types
 *-----------------------------------------------------------------------------*/
using namespace blue_sky;
//CEREAL_REGISTER_TYPE_WITH_NAME(tree::link, "link")
CEREAL_REGISTER_TYPE_WITH_NAME(tree::hard_link, "hard_link")
CEREAL_REGISTER_TYPE_WITH_NAME(tree::weak_link, "weak_link")
CEREAL_REGISTER_TYPE_WITH_NAME(tree::sym_link, "sym_link")
CEREAL_REGISTER_TYPE_WITH_NAME(tree::fusion_link, "fusion_link")

BSS_REGISTER_DYNAMIC_INIT(link)

<|endoftext|>


<commit_before>#include "stdafx.h"
#include "directory_description.h"
#include "directory_comparer.h"
#include "list_directory.h"
#include "directory_mismatch.h"

void test()
{
    list_directory lister;
    directory_description* a(lister.read("C:\\Projects\\kitschensync - Kopie"));
    directory_description* b(lister.read("T:\\kitschensync"));

    directory_comparer dc;
    directory_mismatch* diffs = dc.compare_directories(a, b);
    if (diffs)
    {
        const directory_description* newer;
        const directory_description* older;

        diffs->dump();

        relationship_order ro = diffs->determine_relationship(&newer, &older);
        if (ro != relationship_order::undefined)
        {
            printf("--------------------------------------------\r\n");
            printf("%s is newer than %s\r\n",
                newer->get_path(),
                older->get_path());
            printf("--------------------------------------------\r\n");
            DWORD t0 = GetTickCount();
            diffs->apply_changes(ro, directory_sync_mode::copy_missing_objects_and_delete_obsolete_ones);
            printf("Time to sync directories: %ld ms.\r\n", GetTickCount() - t0);
        }
        else
        {
            printf("*** WARNING: was unable to determine relationship between these two directories...\r\n");
            diffs->dump();
        }
        delete diffs;
        diffs = nullptr;
    }
    else
    {
        printf("Great: directories are identical!\r\n");
    }
    delete a;
    delete b;
}

int _tmain(int, _TCHAR* [])
{
    test();
#ifdef _DEBUG
    _CrtDumpMemoryLeaks();
#endif
    getchar();
    return 0;
}

<commit_msg>handle situation of missing directories better<commit_after>#include "stdafx.h"
#include "directory_description.h"
#include "directory_comparer.h"
#include "list_directory.h"
#include "directory_mismatch.h"
#include "utilities.h"

// todo: make interface for this
bool affirmative_input(const char* fmt, ...)
{
    va_list args;
    va_start(args, fmt);

    std::string formatted(utilities::string::vformat(fmt, args));
    puts(formatted.c_str());

    char input[200];
    if (fgets(input, sizeof(input), stdin))
    {
        if (input[0] == 'y' ||
            input[0] == 'Y')
        {
            return true;
        }
    }
    return false;
}

bool synchronize_directories(const std::string& name_a, const std::string& name_b)
{
    relationship_order ro = relationship_order::undefined;

    if (!file_system::does_directory_exist(name_a))
    {
        if (!file_system::does_directory_exist(name_b))
        {
            printf("ERROR, neither '%s' nor '%s' exist, aborting\r\n",
                name_a.c_str(),
                name_b.c_str());
            return false;
        }

        if (affirmative_input("%s does not exist => do you want to clone %s (Y/n)?",
            name_a.c_str(),
            name_b.c_str()))
        {
            ro = relationship_order::b_newer_than_a;
            if (!file_system::create_directory(name_a.c_str()))
            {
                return false;
            }
        }
        else return false;
    }
    else if (!file_system::does_directory_exist(name_b))
    {
        if (affirmative_input("%s does not exist => do you want to clone %s (Y/n)?",
            name_a.c_str(),
            name_b.c_str()))
        {
            ro = relationship_order::a_newer_than_b;
            if (!file_system::create_directory(name_b.c_str()))
            {
                return false;
            }
        }
        else return false;
    }

    list_directory lister;
    directory_description* a(lister.read(name_a.c_str()));
    directory_description* b(lister.read(name_b.c_str()));

    directory_comparer dc;
    directory_mismatch* diffs = dc.compare_directories(a, b);
    if (diffs)
    {
        const directory_description* newer;
        const directory_description* older;

        relationship_order ro = diffs->determine_relationship(&newer, &older);
        if (ro != relationship_order::undefined)
        {
            printf("--------------------------------------------\r\n");
            printf("%s is newer than %s\r\n",
                newer->get_path(),
                older->get_path());
            printf("--------------------------------------------\r\n");
            //DWORD t0 = GetTickCount();
            //diffs->apply_changes(ro, directory_sync_mode::copy_missing_objects_and_delete_obsolete_ones);
            //printf("Time to sync directories: %ld ms.\r\n", GetTickCount() - t0);
        }
        else
        {
            printf("*** WARNING: was unable to determine relationship between these two directories...\r\n");
            diffs->dump();
        }
        delete diffs;
        diffs = nullptr;
    }
    else
    {
        printf("Great: directories are identical!\r\n");
    }
    delete a;
    delete b;
    return true;
}

int _tmain(int, _TCHAR* [])
{
    synchronize_directories(
        "C:\\Projects\\kitschensync - Kopie",
        "T:\\kitschensync");
#ifdef _DEBUG
    _CrtDumpMemoryLeaks();
#endif
    getchar();
    return 0;
}

<|endoftext|>


<commit_before>#include <string>
#include <QApplication>
#include <QMainWindow>
#include "qIGTLIOClientWidget.h"
#include "vtkIGTLIOLogic.h"
#include "qIGTLIOLogicController.h"

int main(int argc, char** argv)
{
  QApplication app(argc, argv);

  vtkIGTLIOLogicPointer logic = vtkIGTLIOLogicPointer::New();
  qIGTLIOLogicController logicController;
  logicController.setLogic(logic);

  qIGTLIOClientWidget widget;

  widget.setGeometry(0, 0, 859, 811);
  widget.show();
  widget.activateWindow();
  widget.raise();

  int val = app.exec();
  return val;
}
<commit_msg>Fixed crashing qIgtlClient when adding connector from gui.<commit_after>#include <string>
#include <QApplication>
#include <QMainWindow>
#include "qIGTLIOClientWidget.h"
#include "vtkIGTLIOLogic.h"
#include "qIGTLIOLogicController.h"

int main(int argc, char** argv)
{
  QApplication app(argc, argv);

  vtkIGTLIOLogicPointer logic = vtkIGTLIOLogicPointer::New();
  qIGTLIOLogicController logicController;
  logicController.setLogic(logic);

  qIGTLIOClientWidget widget;
  widget.setLogic(logic);

  widget.setGeometry(0, 0, 859, 811);
  widget.show();
  widget.activateWindow();
  widget.raise();

  int val = app.exec();
  return val;
}
<|endoftext|>


<commit_before>/* $Id$ */

/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/**
 * >> Flat structure representing a TPC seed <<
 *
 * To be used in the online and offline calibration schema.
 *
 *
 * Primary Authors : Sergey Gorbunov, Jochen Thaeder, Chiara Zampolli
 *
 **************************************************************************/

#include "AliFlatTPCseed.h"
#include "AliTPCseed.h"
#include "AliHLTTPCTransform.h"
#include "Riostream.h"

void AliFlatTPCseed::SetFromTPCseed( const AliTPCseed *p )
{
  // initialise from AliTPCseed

  Reset();
  if( !p ) return;
  fParam.SetExternalTrackParam(  p );
  fLabel = p->GetLabel();
  for( Int_t irow=0; irow<160; irow++ ){
    AddCluster( p->GetClusterPointer(irow), p->GetTrackPointConst(irow) );
  }
}

void AliFlatTPCseed::GetTPCseed( AliTPCseed *p ) const
{
   // write to AliTPCseed
  if( !p ) return;
  p->Reset();

  AliTPCseed seed;

  fParam.GetExternalTrackParam( seed );
  seed.SetLabel(fLabel);
  seed.SetNumberOfClusters(fNTPCClusters);

  AliTPCclusterMI * clusters = new AliTPCclusterMI[fNTPCClusters];

  const AliFlatTPCCluster *flatClusters = reinterpret_cast< const AliFlatTPCCluster* >( fContent );

  for( Int_t ic=0; ic<fNTPCClusters; ic++){
    const AliFlatTPCCluster &flatCluster = flatClusters[ic];
    int sec = flatCluster.GetSector();
    int row = flatCluster.GetPadRow();
    if(sec >= 36) row = row + AliHLTTPCTransform::GetNRowLow();
    if( row<160 ){
      flatCluster.GetTPCCluster( &(clusters[ic]), seed.GetTrackPoint(row) );
      seed.SetClusterPointer( row , &(clusters[ic]) );
    }
  }
  new (p) AliTPCseed( seed, kTRUE ); // true means that p creates its own cluster objects
  delete [] clusters;
}
<commit_msg>fix bug in setting of TPC clusters in flatTPCseed convertor<commit_after>/* $Id$ */

/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/**
 * >> Flat structure representing a TPC seed <<
 *
 * To be used in the online and offline calibration schema.
 *
 *
 * Primary Authors : Sergey Gorbunov, Jochen Thaeder, Chiara Zampolli
 *
 **************************************************************************/

#include "AliFlatTPCseed.h"
#include "AliTPCseed.h"
#include "AliHLTTPCTransform.h"
#include "Riostream.h"

void AliFlatTPCseed::SetFromTPCseed( const AliTPCseed *p )
{
  // initialise from AliTPCseed

  Reset();
  if( !p ) return;
  fParam.SetExternalTrackParam(  p );
  fLabel = p->GetLabel();
  for( Int_t irow=0; irow<160; irow++ ){
    if( p->GetClusterPointer(irow) ) AddCluster( p->GetClusterPointer(irow), p->GetTrackPointConst(irow) );
  }
}

void AliFlatTPCseed::GetTPCseed( AliTPCseed *p ) const
{
   // write to AliTPCseed
  if( !p ) return;
  p->Reset();

  AliTPCseed seed;

  fParam.GetExternalTrackParam( seed );
  seed.SetLabel(fLabel);
  seed.SetNumberOfClusters(fNTPCClusters);

  AliTPCclusterMI * clusters = new AliTPCclusterMI[fNTPCClusters];

  const AliFlatTPCCluster *flatClusters = reinterpret_cast< const AliFlatTPCCluster* >( fContent );

  for( Int_t ic=0; ic<fNTPCClusters; ic++){
    const AliFlatTPCCluster &flatCluster = flatClusters[ic];
    int sec = flatCluster.GetSector();
    int row = flatCluster.GetPadRow();
    if(sec >= 36) row = row + AliHLTTPCTransform::GetNRowLow();
    if( row<160 ){
      flatCluster.GetTPCCluster( &(clusters[ic]), seed.GetTrackPoint(row) );
      seed.SetClusterPointer( row , &(clusters[ic]) );
    }
  }
  new (p) AliTPCseed( seed, kTRUE ); // true means that p creates its own cluster objects
  delete [] clusters;
}
<|endoftext|>


<commit_before>/*
This file is part of Bohrium and copyright (c) 2012 the Bohrium
team <http://www.bh107.org>.

Bohrium 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 3
of the License, or (at your option) any later version.

Bohrium 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 Lesser General Public License along with Bohrium.

If not, see <http://www.gnu.org/licenses/>.
*/

#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/iostreams/stream_buffer.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/device/back_inserter.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/foreach.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/topological_sort.hpp>
#include <bh.h>
#include <vector>
#include <map>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include "bh_ir.h"

using namespace std;
namespace io = boost::iostreams;

/* Creates a Bohrium Internal Representation (BhIR) from a instruction list.
*
* @ninstr      Number of instructions
* @instr_list  The instruction list
*/
bh_ir::bh_ir(bh_intp ninstr, const bh_instruction instr_list[])
{
    bh_ir::instr_list = vector<bh_instruction>(instr_list, &instr_list[ninstr]);
}

/* Creates a BhIR from a serialized BhIR.
*
* @bhir The BhIr serialized as a char array or vector
*/
bh_ir::bh_ir(const char bhir[], bh_intp size)
{
    io::basic_array_source<char> source(bhir,size);
    io::stream<io::basic_array_source <char> > input_stream(source);
    boost::archive::binary_iarchive ia(input_stream);
    ia >> *this;
}

/* Serialize the BhIR object into a char buffer
*  (use the bh_ir constructor for deserialization)
*
*  @buffer   The char vector to serialize into
*/
void bh_ir::serialize(vector<char> &buffer) const
{
    io::stream<io::back_insert_device<vector<char> > > output_stream(buffer);
    boost::archive::binary_oarchive oa(output_stream);
    oa << *this;
    output_stream.flush();
}

/* Returns the cost of the BhIR */
int bh_ir::cost() const
{
    int cost = 0;
    BOOST_FOREACH(const bh_ir_kernel &k, kernel_list)
    {
        BOOST_FOREACH(const bh_view &v, k.input_list())
        {
            cost += bh_nelements_nbcast(&v) * bh_type_size(v.base->type);
        }
        BOOST_FOREACH(const bh_view &v, k.output_list())
        {
            cost += bh_nelements_nbcast(&v) * bh_type_size(v.base->type);
        }
    }
    return cost;
}

/* Pretty print the kernel list */
void bh_ir::pprint_kernel_list() const
{
    char msg[100]; int i=0;
    BOOST_FOREACH(const bh_ir_kernel &k, kernel_list)
    {
        snprintf(msg, 100, "kernel-%d", i++);
        bh_pprint_instr_list(&k.instr_list()[0], k.instr_list().size(), msg);
    }
}

/* Pretty write the kernel DAG as a DOT file
*
*  @filename   Name of the DOT file
*/
void bh_ir::pprint_kernel_dag(const char filename[]) const
{
    using namespace boost;
    typedef adjacency_list<setS, vecS, bidirectionalS, const bh_ir_kernel*> Graph;
    typedef graph_traits<Graph>::vertex_descriptor Vertex;
    Graph dag;
    BOOST_FOREACH(const bh_ir_kernel &kernel, kernel_list)
    {
        Vertex new_v = add_vertex(&kernel, dag);

        //Add dependencies
        BOOST_FOREACH(Vertex v, vertices(dag))
        {
            if(new_v != v)//We do not depend on ourself
            {
                if(kernel.dependency(*dag[v]))
                    add_edge(v, new_v, dag);
            }
        }
    }
    stringstream header;
    header << "labelloc=\"t\";" << endl;
    header << "label=\"DAG with a total cost of " << (cost()/1024) << " kbytes\";" << endl;
    bh_pprint_dag_file<Graph>(dag, filename, header.str().c_str());
}

/* Determines whether there are cyclic dependencies between the kernels in the BhIR
*
*  @index_map  A map from an instruction in the kernel_list (a pair of a kernel and
*              an instruction index) to an index into the original instruction list
*  @return     True when no cycles was found
*/
bool bh_ir::check_kernel_cycles(const map<pair<int,int>,int> index_map) const
{
    //Create a DAG of the kernels and check for cycles
    using namespace boost;
    typedef adjacency_list<setS, vecS, bidirectionalS, const bh_ir_kernel*> Graph;
    typedef graph_traits<Graph>::vertex_descriptor Vertex;

    Graph dag(kernel_list.size());

    //First we build a map from a index in the original instruction list
    //to a vertex in the 'dag'
    map<int,Vertex> instr2vertex;
    unsigned int k=0;
    BOOST_FOREACH(Vertex v, vertices(dag))
    {
        const vector<bh_instruction> &kernel = kernel_list[k].instr_list();
        dag[v] = &kernel_list[k];
        for(unsigned int i=0; i<kernel.size(); ++i)
        {
            int instr_index = index_map.at(make_pair(k,i));
            instr2vertex.insert(pair<int,Vertex>(instr_index,v));
        }
        ++k;
    }
    //Then we add edges to the 'dag' for each dependency in the original
    //instruction list
    for(unsigned int i=0; i<instr_list.size(); ++i)
    {
        Vertex v = instr2vertex[i];
        for(unsigned int j=0; j<i; ++j)//We may depend on any previous instruction
        {
            if(bh_instr_dependency(&instr_list[i], &instr_list[j]))
            {
                if(instr2vertex[j] != v)
                    add_edge(instr2vertex[j], v, dag);
            }
        }
    }
    //Finally we check for cycles between the kernel dependencies
    vector<Vertex> topological_order;
    try
    {
        //TODO: topological sort is an efficient method for finding cycles,
        //but we should avoid allocating a vector
        topological_sort(dag, back_inserter(topological_order));
        return true;
    }
    catch (const not_a_dag &e)
    {
        bh_pprint_dag_file<Graph>(dag, "check_kernel_cycles-fail.dot");
        return false;
    }
}

/* Add an instruction to the kernel
 *
 * @instr   The instruction to add
 * @return  The boolean answer
 */
void bh_ir_kernel::add_instr(const bh_instruction &instr)
{
    instrs.push_back(instr);

    if(instr.opcode == BH_DISCARD)
    {
        const bh_base *base = instr.operand[0].base;
        for(vector<bh_view>::iterator it=outputs.begin(); it != outputs.end(); ++it)
        {
            if(base == it->base)
            {
                temps.push_back(base);
                outputs.erase(it);
                break;
            }
        }
    }
    else if(instr.opcode != BH_FREE)
    {
        {
            const bh_view &v = instr.operand[0];
            BOOST_FOREACH(const bh_view &i, outputs)
            {
                if(bh_view_identical(&v, &i))
                    return;
            }
            outputs.push_back(v);
        }
        const int nop = bh_operands(instr.opcode);
        for(int i=1; i<nop; ++i)
        {
            const bh_view &v = instr.operand[i];
            if(!bh_is_constant(&v))
            {
                BOOST_FOREACH(const bh_view &i, inputs)
                {
                    if(bh_view_identical(&v, &i))
                        return;
                }
                inputs.push_back(v);
            }
        }
    }
};

/* Determines whether it is legal to fuse with the kernel
 *
 * @other The other kernel
 * @return The boolean answer
 */
bool bh_ir_kernel::fusible(const bh_ir_kernel &other) const
{
    BOOST_FOREACH(const bh_instruction &a, instr_list())
    {
        BOOST_FOREACH(const bh_instruction &b, other.instr_list())
        {
            if(not bh_instr_fusible(&a, &b))
                return false;
        }
    }
    return true;
}

/* Determines whether this kernel depends on 'other',
 * which is true when:
 *      'other' writes to an array that 'this' access
 *                        or
 *      'this' writes to an array that 'other' access
 *
 * @other The other kernel
 * @return The boolean answer
 */
bool bh_ir_kernel::dependency(const bh_ir_kernel &other) const
{
    BOOST_FOREACH(const bh_instruction &i, instr_list())
    {
        BOOST_FOREACH(const bh_instruction &o, other.instr_list())
        {
            if(bh_instr_dependency(&i, &o))
                return true;
        }
    }
    return false;
}

/* Determines whether it is legal to fuse with the instruction
 *
 * @instr  The instruction
 * @return The boolean answer
 */
bool bh_ir_kernel::fusible(const bh_instruction &instr) const
{
    BOOST_FOREACH(const bh_instruction &i, instr_list())
    {
        if(not bh_instr_fusible(&i, &instr))
            return false;
    }
    return true;
}

<commit_msg>bhir: now bh_ir_kernel::add_instr() checks for local sources<commit_after>/*
This file is part of Bohrium and copyright (c) 2012 the Bohrium
team <http://www.bh107.org>.

Bohrium 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 3
of the License, or (at your option) any later version.

Bohrium 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 Lesser General Public License along with Bohrium.

If not, see <http://www.gnu.org/licenses/>.
*/

#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/iostreams/stream_buffer.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/device/back_inserter.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/foreach.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/topological_sort.hpp>
#include <bh.h>
#include <vector>
#include <map>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include "bh_ir.h"

using namespace std;
namespace io = boost::iostreams;

/* Creates a Bohrium Internal Representation (BhIR) from a instruction list.
*
* @ninstr      Number of instructions
* @instr_list  The instruction list
*/
bh_ir::bh_ir(bh_intp ninstr, const bh_instruction instr_list[])
{
    bh_ir::instr_list = vector<bh_instruction>(instr_list, &instr_list[ninstr]);
}

/* Creates a BhIR from a serialized BhIR.
*
* @bhir The BhIr serialized as a char array or vector
*/
bh_ir::bh_ir(const char bhir[], bh_intp size)
{
    io::basic_array_source<char> source(bhir,size);
    io::stream<io::basic_array_source <char> > input_stream(source);
    boost::archive::binary_iarchive ia(input_stream);
    ia >> *this;
}

/* Serialize the BhIR object into a char buffer
*  (use the bh_ir constructor for deserialization)
*
*  @buffer   The char vector to serialize into
*/
void bh_ir::serialize(vector<char> &buffer) const
{
    io::stream<io::back_insert_device<vector<char> > > output_stream(buffer);
    boost::archive::binary_oarchive oa(output_stream);
    oa << *this;
    output_stream.flush();
}

/* Returns the cost of the BhIR */
int bh_ir::cost() const
{
    int cost = 0;
    BOOST_FOREACH(const bh_ir_kernel &k, kernel_list)
    {
        BOOST_FOREACH(const bh_view &v, k.input_list())
        {
            cost += bh_nelements_nbcast(&v) * bh_type_size(v.base->type);
        }
        BOOST_FOREACH(const bh_view &v, k.output_list())
        {
            cost += bh_nelements_nbcast(&v) * bh_type_size(v.base->type);
        }
    }
    return cost;
}

/* Pretty print the kernel list */
void bh_ir::pprint_kernel_list() const
{
    char msg[100]; int i=0;
    BOOST_FOREACH(const bh_ir_kernel &k, kernel_list)
    {
        snprintf(msg, 100, "kernel-%d", i++);
        bh_pprint_instr_list(&k.instr_list()[0], k.instr_list().size(), msg);
    }
}

/* Pretty write the kernel DAG as a DOT file
*
*  @filename   Name of the DOT file
*/
void bh_ir::pprint_kernel_dag(const char filename[]) const
{
    using namespace boost;
    typedef adjacency_list<setS, vecS, bidirectionalS, const bh_ir_kernel*> Graph;
    typedef graph_traits<Graph>::vertex_descriptor Vertex;
    Graph dag;
    BOOST_FOREACH(const bh_ir_kernel &kernel, kernel_list)
    {
        Vertex new_v = add_vertex(&kernel, dag);

        //Add dependencies
        BOOST_FOREACH(Vertex v, vertices(dag))
        {
            if(new_v != v)//We do not depend on ourself
            {
                if(kernel.dependency(*dag[v]))
                    add_edge(v, new_v, dag);
            }
        }
    }
    stringstream header;
    header << "labelloc=\"t\";" << endl;
    header << "label=\"DAG with a total cost of " << (cost()/1024) << " kbytes\";" << endl;
    bh_pprint_dag_file<Graph>(dag, filename, header.str().c_str());
}

/* Determines whether there are cyclic dependencies between the kernels in the BhIR
*
*  @index_map  A map from an instruction in the kernel_list (a pair of a kernel and
*              an instruction index) to an index into the original instruction list
*  @return     True when no cycles was found
*/
bool bh_ir::check_kernel_cycles(const map<pair<int,int>,int> index_map) const
{
    //Create a DAG of the kernels and check for cycles
    using namespace boost;
    typedef adjacency_list<setS, vecS, bidirectionalS, const bh_ir_kernel*> Graph;
    typedef graph_traits<Graph>::vertex_descriptor Vertex;

    Graph dag(kernel_list.size());

    //First we build a map from an index in the original instruction list
    //to a vertex in the 'dag'
    map<int,Vertex> instr2vertex;
    unsigned int k=0;
    BOOST_FOREACH(Vertex v, vertices(dag))
    {
        const vector<bh_instruction> &kernel = kernel_list[k].instr_list();
        dag[v] = &kernel_list[k];
        for(unsigned int i=0; i<kernel.size(); ++i)
        {
            int instr_index = index_map.at(make_pair(k,i));
            instr2vertex.insert(pair<int,Vertex>(instr_index,v));
        }
        ++k;
    }
    //Then we add edges to the 'dag' for each dependency in the original
    //instruction list
    for(unsigned int i=0; i<instr_list.size(); ++i)
    {
        Vertex v = instr2vertex[i];
        for(unsigned int j=0; j<i; ++j)//We may depend on any previous instruction
        {
            if(bh_instr_dependency(&instr_list[i], &instr_list[j]))
            {
                if(instr2vertex[j] != v)
                    add_edge(instr2vertex[j], v, dag);
            }
        }
    }
    //Finally we check for cycles between the kernel dependencies
    vector<Vertex> topological_order;
    try
    {
        //TODO: topological sort is an efficient method for finding cycles,
        //but we should avoid allocating a vector
        topological_sort(dag, back_inserter(topological_order));
        return true;
    }
    catch (const not_a_dag &e)
    {
        cout << "Writing the failed kernel list: check_kernel_cycles-fail.dot" << endl;
        bh_pprint_dag_file<Graph>(dag, "check_kernel_cycles-fail.dot");
        return false;
    }
}

/* Add an instruction to the kernel
 *
 * @instr   The instruction to add
 * @return  The boolean answer
 */
void bh_ir_kernel::add_instr(const bh_instruction &instr)
{
    if(instr.opcode == BH_DISCARD)
    {
        const bh_base *base = instr.operand[0].base;
        for(vector<bh_view>::iterator it=outputs.begin(); it != outputs.end(); ++it)
        {
            if(base == it->base)
            {
                temps.push_back(base);
                outputs.erase(it);
                break;
            }
        }
    }
    else if(instr.opcode != BH_FREE)
    {
        {
            bool duplicates = false;
            const bh_view &v = instr.operand[0];
            BOOST_FOREACH(const bh_view &i, outputs)
            {
                if(bh_view_identical(&v, &i))
                {
                    duplicates = true;
                    break;
                }
            }
            if(!duplicates)
                outputs.push_back(v);
        }
        const int nop = bh_operands(instr.opcode);
        for(int i=1; i<nop; ++i)
        {
            const bh_view &v = instr.operand[i];
            if(bh_is_constant(&v))
                continue;

            bool duplicates = false;
            BOOST_FOREACH(const bh_view &i, inputs)
            {
                if(bh_view_identical(&v, &i))
                {
                    duplicates = true;
                    break;
                }
            }
            if(duplicates)
                continue;

            bool local_source = false;
            BOOST_FOREACH(const bh_instruction &i, instrs)
            {
                if(bh_view_identical(&v, &i.operand[0]))
                {
                    local_source = true;
                    break;
                }
            }
            if(!local_source)
                inputs.push_back(v);
        }
    }
    instrs.push_back(instr);
};

/* Determines whether it is legal to fuse with the kernel
 *
 * @other The other kernel
 * @return The boolean answer
 */
bool bh_ir_kernel::fusible(const bh_ir_kernel &other) const
{
    BOOST_FOREACH(const bh_instruction &a, instr_list())
    {
        BOOST_FOREACH(const bh_instruction &b, other.instr_list())
        {
            if(not bh_instr_fusible(&a, &b))
                return false;
        }
    }
    return true;
}

/* Determines whether this kernel depends on 'other',
 * which is true when:
 *      'other' writes to an array that 'this' access
 *                        or
 *      'this' writes to an array that 'other' access
 *
 * @other The other kernel
 * @return The boolean answer
 */
bool bh_ir_kernel::dependency(const bh_ir_kernel &other) const
{
    BOOST_FOREACH(const bh_instruction &i, instr_list())
    {
        BOOST_FOREACH(const bh_instruction &o, other.instr_list())
        {
            if(bh_instr_dependency(&i, &o))
                return true;
        }
    }
    return false;
}

/* Determines whether it is legal to fuse with the instruction
 *
 * @instr  The instruction
 * @return The boolean answer
 */
bool bh_ir_kernel::fusible(const bh_instruction &instr) const
{
    BOOST_FOREACH(const bh_instruction &i, instr_list())
    {
        if(not bh_instr_fusible(&i, &instr))
            return false;
    }
    return true;
}

<|endoftext|>


<commit_before>// @(#)root/memstat:$Id$
// Author: Anar Manafov (A.Manafov@gsi.de) 2008-03-02

/*************************************************************************
* Copyright (C) 1995-2010, Rene Brun and Fons Rademakers.               *
* All rights reserved.                                                  *
*                                                                       *
* For the licensing terms see $ROOTSYS/LICENSE.                         *
* For the list of contributors see $ROOTSYS/README/CREDITS.             *
*************************************************************************/
// STD
#include <cstdlib>
// ROOT
#include "TSystem.h"
#include "TEnv.h"
#include "TError.h"
#include "Riostream.h"
#include "TObject.h"
#include "TFile.h"
#include "TTree.h"
#include "TArrayL64.h"
#include "TH1.h"
#include "TMD5.h"
// Memstat
#include "TMemStatBacktrace.h"
#include "TMemStatMng.h"

using namespace memstat;

ClassImp(TMemStatMng)

TMemStatMng* TMemStatMng::fgInstance = NULL;

//****************************************************************************//
//
//****************************************************************************//

TMemStatMng::TMemStatMng():
   TObject(),
#if !defined(__APPLE__)
   fPreviousMallocHook(TMemStatHook::GetMallocHook()),
   fPreviousFreeHook(TMemStatHook::GetFreeHook()),
#endif
   fDumpTree(NULL),
   fUseGNUBuiltinBacktrace(kFALSE),
   fBeginTime(0),
   fPos(0),
   fTimems(0),
   fNBytes(0),
   fN(0),
   fBtID(0),
   fBTCount(0),
   fBTIDCount(0),
   fSysInfo(NULL)
{
   // Default constructor
}

//______________________________________________________________________________
void TMemStatMng::Init()
{
   //Initialize MemStat manager - used only by instance method

   fBeginTime = fTimeStamp.AsDouble();

   fDumpFile = new TFile(Form("memstat_%d.root", gSystem->GetPid()), "recreate");
   Int_t opt = 200000;
   if(!fDumpTree) {
      fDumpTree = new TTree("T", "Memory Statistics");
      fDumpTree->Branch("pos",   &fPos,   "pos/l", opt);
      fDumpTree->Branch("time",  &fTimems, "time/I", opt);
      fDumpTree->Branch("nbytes", &fNBytes, "nbytes/I", opt);
      fDumpTree->Branch("btid",  &fBtID,  "btid/I", opt);
   }

   fBTCount = 0;

   fBTIDCount = 0;

   fFAddrsList = new TObjArray();
   fFAddrsList->SetOwner(kTRUE);
   fFAddrsList->SetName("FAddrsList");

   fHbtids  = new TH1I("btids", "table of btids", 10000, 0, 1);   //where fHbtids is a member of the manager class
   fHbtids->SetDirectory(0);
   // save the histogram and the TObjArray to the tree header
   fDumpTree->GetUserInfo()->Add(fHbtids);
   fDumpTree->GetUserInfo()->Add(fFAddrsList);
   // save the system info to a tree header
   string sSysInfo(gSystem->GetBuildNode());
   sSysInfo += " | ";
   sSysInfo += gSystem->GetBuildCompilerVersion();
   sSysInfo += " | ";
   sSysInfo += gSystem->GetFlagsDebug();
   sSysInfo += " ";
   sSysInfo += gSystem->GetFlagsOpt();
   fSysInfo = new TNamed("SysInfo", sSysInfo.c_str());

   fDumpTree->GetUserInfo()->Add(fSysInfo);
   fDumpTree->SetAutoSave(10000000);
}

//______________________________________________________________________________
TMemStatMng* TMemStatMng::GetInstance()
{
   // GetInstance - a static function
   // Initialize a singleton of MemStat manager

   if(!fgInstance) {
      fgInstance = new TMemStatMng;
      fgInstance->Init();
   }
   return fgInstance;
}

//______________________________________________________________________________
void TMemStatMng::Close()
{
   // Close - a static function
   // This method stops the manager,
   // flashes all the buffered data and closes the output tree.

   // TODO: This is a temporary solution until we find a properalgorithm for SaveData
   //fgInstance->fDumpFile->WriteObject(fgInstance->fFAddrsList, "FAddrsList");

   // to be documented
   printf("TMemStatMng::Close called\n");
   fgInstance->fDumpTree->AutoSave();
   fgInstance->fDumpTree->GetUserInfo()->Delete();

   //delete fgInstance->fFAddrsList;
   //delete fgInstance->fSysInfo;

   delete fgInstance;
   fgInstance = NULL;
}

//______________________________________________________________________________
TMemStatMng::~TMemStatMng()
{
   // if an instance is destructed - the hooks are reseted to old hooks

   if(this != TMemStatMng::GetInstance())
      return;

   Info("~TMemStatMng", ">>> All free/malloc calls count: %d", fBTIDCount);
   Info("~TMemStatMng", ">>> Unique BTIDs count: %zu", fBTChecksums.size());

   Disable();
}

//______________________________________________________________________________
void TMemStatMng::Enable()
{
   // Enable memory hooks

   if(this != GetInstance())
      return;
#if defined(__APPLE__)
   TMemStatHook::trackZoneMalloc(MacAllocHook, MacFreeHook);
#else
   // set hook to our functions
   TMemStatHook::SetMallocHook(AllocHook);
   TMemStatHook::SetFreeHook(FreeHook);
#endif
}

//______________________________________________________________________________
void TMemStatMng::Disable()
{
   // Disble memory hooks

   if(this != GetInstance())
      return;
#if defined(__APPLE__)
   TMemStatHook::untrackZoneMalloc();
#else
   // set hook to our functions
   TMemStatHook::SetMallocHook(fPreviousMallocHook);
   TMemStatHook::SetFreeHook(fPreviousFreeHook);
#endif
}

//______________________________________________________________________________
void TMemStatMng::MacAllocHook(void *ptr, size_t size)
{
   // AllocHook - a static function
   // a special memory hook for Mac OS X memory zones.
   // Triggered when memory is allocated.

   TMemStatMng* instance = TMemStatMng::GetInstance();
   // Restore all old hooks
   instance->Disable();

   // Call our routine
   instance->AddPointer(ptr, Int_t(size));

   // Restore our own hooks
   instance->Enable();
}

//______________________________________________________________________________
void TMemStatMng::MacFreeHook(void *ptr)
{
   // AllocHook - a static function
   // a special memory hook for Mac OS X memory zones.
   // Triggered when memory is deallocated.

   TMemStatMng* instance = TMemStatMng::GetInstance();
   // Restore all old hooks
   instance->Disable();

   // Call our routine
   instance->AddPointer(ptr, -1);

   // Restore our own hooks
   instance->Enable();
}

//______________________________________________________________________________
void *TMemStatMng::AllocHook(size_t size, const void* /*caller*/)
{
   // AllocHook - a static function
   // A glibc memory allocation hook.

   TMemStatMng* instance = TMemStatMng::GetInstance();
   // Restore all old hooks
   instance->Disable();

   // Call recursively
   void *result = malloc(size);
   // Call our routine
   instance->AddPointer(result, Int_t(size));
   //  TTimer::SingleShot(0, "TYamsMemMng", instance, "SaveData()");

   // Restore our own hooks
   instance->Enable();

   return result;
}

//______________________________________________________________________________
void TMemStatMng::FreeHook(void* ptr, const void* /*caller*/)
{
   // FreeHook - a static function
   // A glibc memory deallocation hook.

   TMemStatMng* instance = TMemStatMng::GetInstance();
   // Restore all old hooks
   instance->Disable();

   // Call recursively
   free(ptr);

   // Call our routine
   instance->AddPointer(ptr, -1);

   // Restore our own hooks
   instance->Enable();
}

//______________________________________________________________________________
void TMemStatMng::AddPointer(void *ptr, Int_t size)
{
   // Add pointer to table.
   // This method is called every time when any of the hooks are triggered.
   // The memory de-/allocation information will is recorded.

   void *stptr[g_BTStackLevel + 1];
   const int stackentries = getBacktrace(stptr, g_BTStackLevel, fUseGNUBuiltinBacktrace);

   // save only unique BTs
   TMD5 md5;
   md5.Update(reinterpret_cast<UChar_t*>(stptr), sizeof(void*) * stackentries);
   md5.Final();
   string crc_digest(md5.AsString());

   // for Debug. A counter of all (de)allacations.
   ++fBTIDCount;

   CRCSet_t::const_iterator found = fBTChecksums.find(crc_digest);
   // TODO: define a proper default value
   Int_t btid = -1;
   if(fBTChecksums.end() == found) {
      // check the size of the BT array container
      const int nbins = fHbtids->GetNbinsX();
      //check that the current allocation in fHbtids is enough, otherwise expend it with
      if(fBTCount + stackentries + 1 >= nbins) {
         fHbtids->SetBins(nbins * 2, 0, 1);
      }

      int *btids = fHbtids->GetArray();
      // A first value is a number of entries in a given stack
      btids[fBTCount++] = stackentries;
      btid = fBTCount;
      if(stackentries <= 0) {
         Warning("AddPointer",
                 "A number of stack entries is equal or less than zero. For btid %d", btid);
      }

      // add new BT's CRC value
      pair<CRCSet_t::iterator, bool> res = fBTChecksums.insert(CRCSet_t::value_type(crc_digest, btid));
      if(!res.second)
         Error("AddPointer", "Can't added a new BTID to the container.");

      // save all symbols of this BT
      for(int i = 0; i < stackentries; ++i) {
         ULong_t func_addr = (ULong_t)(stptr[i]);
         Int_t idx = fFAddrs.find(func_addr);
         // check, whether it's a new symbol
         if(idx < 0) {
            TString strFuncAddr;
            strFuncAddr += func_addr;
            TString strSymbolInfo;
            getSymbolFullInfo(stptr[i], &strSymbolInfo);

            TNamed *nm = new TNamed(strFuncAddr, strSymbolInfo);
            fFAddrsList->Add(nm);
            idx = fFAddrsList->GetEntriesFast() - 1;
            // TODO: more detailed error message...
            if(!fFAddrs.add(func_addr, idx))
               Error("AddPointer", "Can't add a function return address to the container");
         }

         // even if we have -1 as an index we add it to the container
         btids[fBTCount++] = idx;
      }

   } else {
      // reuse an existing BT
      btid = found->second;
   }

   if(btid <= 0)
      Error("AddPointer", "bad BT id");

   fTimeStamp.Set();
   Double_t CurTime = fTimeStamp.AsDouble();
   fTimems = Int_t(10000.*(CurTime - fBeginTime));
   ULong_t ul = (ULong_t)(ptr);
   fPos    = (ULong64_t)(ul);
   fNBytes = size;
   fN      = 0;
   fBtID   = btid;
   fDumpTree->Fill();
}

<commit_msg>Initialize all members in constructor. coverity CID11113<commit_after>// @(#)root/memstat:$Id$
// Author: Anar Manafov (A.Manafov@gsi.de) 2008-03-02

/*************************************************************************
* Copyright (C) 1995-2010, Rene Brun and Fons Rademakers.               *
* All rights reserved.                                                  *
*                                                                       *
* For the licensing terms see $ROOTSYS/LICENSE.                         *
* For the list of contributors see $ROOTSYS/README/CREDITS.             *
*************************************************************************/
// STD
#include <cstdlib>
// ROOT
#include "TSystem.h"
#include "TEnv.h"
#include "TError.h"
#include "Riostream.h"
#include "TObject.h"
#include "TFile.h"
#include "TTree.h"
#include "TArrayL64.h"
#include "TH1.h"
#include "TMD5.h"
// Memstat
#include "TMemStatBacktrace.h"
#include "TMemStatMng.h"

using namespace memstat;

ClassImp(TMemStatMng)

TMemStatMng* TMemStatMng::fgInstance = NULL;

//****************************************************************************//
//
//****************************************************************************//

TMemStatMng::TMemStatMng():
   TObject(),
#if !defined(__APPLE__)
   fPreviousMallocHook(TMemStatHook::GetMallocHook()),
   fPreviousFreeHook(TMemStatHook::GetFreeHook()),
#endif
   fDumpFile(NULL),
   fDumpTree(NULL),
   fUseGNUBuiltinBacktrace(kFALSE),
   fBeginTime(0),
   fPos(0),
   fTimems(0),
   fNBytes(0),
   fN(0),
   fBtID(0),
   fFAddrsList(0),
   fHbtids(0),
   fBTCount(0),
   fBTIDCount(0),
   fSysInfo(NULL)
{
   // Default constructor
}

//______________________________________________________________________________
void TMemStatMng::Init()
{
   //Initialize MemStat manager - used only by instance method

   fBeginTime = fTimeStamp.AsDouble();

   fDumpFile = new TFile(Form("memstat_%d.root", gSystem->GetPid()), "recreate");
   Int_t opt = 200000;
   if(!fDumpTree) {
      fDumpTree = new TTree("T", "Memory Statistics");
      fDumpTree->Branch("pos",   &fPos,   "pos/l", opt);
      fDumpTree->Branch("time",  &fTimems, "time/I", opt);
      fDumpTree->Branch("nbytes", &fNBytes, "nbytes/I", opt);
      fDumpTree->Branch("btid",  &fBtID,  "btid/I", opt);
   }

   fBTCount = 0;

   fBTIDCount = 0;

   fFAddrsList = new TObjArray();
   fFAddrsList->SetOwner(kTRUE);
   fFAddrsList->SetName("FAddrsList");

   fHbtids  = new TH1I("btids", "table of btids", 10000, 0, 1);   //where fHbtids is a member of the manager class
   fHbtids->SetDirectory(0);
   // save the histogram and the TObjArray to the tree header
   fDumpTree->GetUserInfo()->Add(fHbtids);
   fDumpTree->GetUserInfo()->Add(fFAddrsList);
   // save the system info to a tree header
   string sSysInfo(gSystem->GetBuildNode());
   sSysInfo += " | ";
   sSysInfo += gSystem->GetBuildCompilerVersion();
   sSysInfo += " | ";
   sSysInfo += gSystem->GetFlagsDebug();
   sSysInfo += " ";
   sSysInfo += gSystem->GetFlagsOpt();
   fSysInfo = new TNamed("SysInfo", sSysInfo.c_str());

   fDumpTree->GetUserInfo()->Add(fSysInfo);
   fDumpTree->SetAutoSave(10000000);
}

//______________________________________________________________________________
TMemStatMng* TMemStatMng::GetInstance()
{
   // GetInstance - a static function
   // Initialize a singleton of MemStat manager

   if(!fgInstance) {
      fgInstance = new TMemStatMng;
      fgInstance->Init();
   }
   return fgInstance;
}

//______________________________________________________________________________
void TMemStatMng::Close()
{
   // Close - a static function
   // This method stops the manager,
   // flashes all the buffered data and closes the output tree.

   // TODO: This is a temporary solution until we find a properalgorithm for SaveData
   //fgInstance->fDumpFile->WriteObject(fgInstance->fFAddrsList, "FAddrsList");

   // to be documented
   printf("TMemStatMng::Close called\n");
   fgInstance->fDumpTree->AutoSave();
   fgInstance->fDumpTree->GetUserInfo()->Delete();

   //delete fgInstance->fFAddrsList;
   //delete fgInstance->fSysInfo;

   delete fgInstance;
   fgInstance = NULL;
}

//______________________________________________________________________________
TMemStatMng::~TMemStatMng()
{
   // if an instance is destructed - the hooks are reseted to old hooks

   if(this != TMemStatMng::GetInstance())
      return;

   Info("~TMemStatMng", ">>> All free/malloc calls count: %d", fBTIDCount);
   Info("~TMemStatMng", ">>> Unique BTIDs count: %zu", fBTChecksums.size());

   Disable();
}

//______________________________________________________________________________
void TMemStatMng::Enable()
{
   // Enable memory hooks

   if(this != GetInstance())
      return;
#if defined(__APPLE__)
   TMemStatHook::trackZoneMalloc(MacAllocHook, MacFreeHook);
#else
   // set hook to our functions
   TMemStatHook::SetMallocHook(AllocHook);
   TMemStatHook::SetFreeHook(FreeHook);
#endif
}

//______________________________________________________________________________
void TMemStatMng::Disable()
{
   // Disble memory hooks

   if(this != GetInstance())
      return;
#if defined(__APPLE__)
   TMemStatHook::untrackZoneMalloc();
#else
   // set hook to our functions
   TMemStatHook::SetMallocHook(fPreviousMallocHook);
   TMemStatHook::SetFreeHook(fPreviousFreeHook);
#endif
}

//______________________________________________________________________________
void TMemStatMng::MacAllocHook(void *ptr, size_t size)
{
   // AllocHook - a static function
   // a special memory hook for Mac OS X memory zones.
   // Triggered when memory is allocated.

   TMemStatMng* instance = TMemStatMng::GetInstance();
   // Restore all old hooks
   instance->Disable();

   // Call our routine
   instance->AddPointer(ptr, Int_t(size));

   // Restore our own hooks
   instance->Enable();
}

//______________________________________________________________________________
void TMemStatMng::MacFreeHook(void *ptr)
{
   // AllocHook - a static function
   // a special memory hook for Mac OS X memory zones.
   // Triggered when memory is deallocated.

   TMemStatMng* instance = TMemStatMng::GetInstance();
   // Restore all old hooks
   instance->Disable();

   // Call our routine
   instance->AddPointer(ptr, -1);

   // Restore our own hooks
   instance->Enable();
}

//______________________________________________________________________________
void *TMemStatMng::AllocHook(size_t size, const void* /*caller*/)
{
   // AllocHook - a static function
   // A glibc memory allocation hook.

   TMemStatMng* instance = TMemStatMng::GetInstance();
   // Restore all old hooks
   instance->Disable();

   // Call recursively
   void *result = malloc(size);
   // Call our routine
   instance->AddPointer(result, Int_t(size));
   //  TTimer::SingleShot(0, "TYamsMemMng", instance, "SaveData()");

   // Restore our own hooks
   instance->Enable();

   return result;
}

//______________________________________________________________________________
void TMemStatMng::FreeHook(void* ptr, const void* /*caller*/)
{
   // FreeHook - a static function
   // A glibc memory deallocation hook.

   TMemStatMng* instance = TMemStatMng::GetInstance();
   // Restore all old hooks
   instance->Disable();

   // Call recursively
   free(ptr);

   // Call our routine
   instance->AddPointer(ptr, -1);

   // Restore our own hooks
   instance->Enable();
}

//______________________________________________________________________________
void TMemStatMng::AddPointer(void *ptr, Int_t size)
{
   // Add pointer to table.
   // This method is called every time when any of the hooks are triggered.
   // The memory de-/allocation information will is recorded.

   void *stptr[g_BTStackLevel + 1];
   const int stackentries = getBacktrace(stptr, g_BTStackLevel, fUseGNUBuiltinBacktrace);

   // save only unique BTs
   TMD5 md5;
   md5.Update(reinterpret_cast<UChar_t*>(stptr), sizeof(void*) * stackentries);
   md5.Final();
   string crc_digest(md5.AsString());

   // for Debug. A counter of all (de)allacations.
   ++fBTIDCount;

   CRCSet_t::const_iterator found = fBTChecksums.find(crc_digest);
   // TODO: define a proper default value
   Int_t btid = -1;
   if(fBTChecksums.end() == found) {
      // check the size of the BT array container
      const int nbins = fHbtids->GetNbinsX();
      //check that the current allocation in fHbtids is enough, otherwise expend it with
      if(fBTCount + stackentries + 1 >= nbins) {
         fHbtids->SetBins(nbins * 2, 0, 1);
      }

      int *btids = fHbtids->GetArray();
      // A first value is a number of entries in a given stack
      btids[fBTCount++] = stackentries;
      btid = fBTCount;
      if(stackentries <= 0) {
         Warning("AddPointer",
                 "A number of stack entries is equal or less than zero. For btid %d", btid);
      }

      // add new BT's CRC value
      pair<CRCSet_t::iterator, bool> res = fBTChecksums.insert(CRCSet_t::value_type(crc_digest, btid));
      if(!res.second)
         Error("AddPointer", "Can't added a new BTID to the container.");

      // save all symbols of this BT
      for(int i = 0; i < stackentries; ++i) {
         ULong_t func_addr = (ULong_t)(stptr[i]);
         Int_t idx = fFAddrs.find(func_addr);
         // check, whether it's a new symbol
         if(idx < 0) {
            TString strFuncAddr;
            strFuncAddr += func_addr;
            TString strSymbolInfo;
            getSymbolFullInfo(stptr[i], &strSymbolInfo);

            TNamed *nm = new TNamed(strFuncAddr, strSymbolInfo);
            fFAddrsList->Add(nm);
            idx = fFAddrsList->GetEntriesFast() - 1;
            // TODO: more detailed error message...
            if(!fFAddrs.add(func_addr, idx))
               Error("AddPointer", "Can't add a function return address to the container");
         }

         // even if we have -1 as an index we add it to the container
         btids[fBTCount++] = idx;
      }

   } else {
      // reuse an existing BT
      btid = found->second;
   }

   if(btid <= 0)
      Error("AddPointer", "bad BT id");

   fTimeStamp.Set();
   Double_t CurTime = fTimeStamp.AsDouble();
   fTimems = Int_t(10000.*(CurTime - fBeginTime));
   ULong_t ul = (ULong_t)(ptr);
   fPos    = (ULong64_t)(ul);
   fNBytes = size;
   fN      = 0;
   fBtID   = btid;
   fDumpTree->Fill();
}

<|endoftext|>


<commit_before>#ifndef MJOLNIR_LOCAL_FORCE_FIELD
#define MJOLNIR_LOCAL_FORCE_FIELD
#include "LocalInteractionBase.hpp"
#include <mjolnir/util/logger.hpp>
#include <utility>
#include <vector>
#include <array>
#include <memory>

namespace mjolnir
{

template<typename traitsT>
class LocalForceField
{
  public:
    typedef traitsT traits_type;
    typedef typename traits_type::real_type         real_type;
    typedef typename traits_type::coordinate_type   coordinate_type;
    typedef System<traits_type>                     system_type;
    typedef typename system_type::particle_type     particle_type;
    typedef LocalInteractionBase<traitsT>           interaction_type;
    typedef std::unique_ptr<interaction_type>       interaction_ptr;
    typedef std::vector<interaction_ptr>            container_type;
    typedef typename container_type::iterator       iterator;
    typedef typename container_type::const_iterator const_iterator;

  public:

    LocalForceField()  = default;
    ~LocalForceField() = default;
    LocalForceField(LocalForceField const&) = delete;
    LocalForceField(LocalForceField&&)      = default;
    LocalForceField& operator=(LocalForceField const&) = delete;
    LocalForceField& operator=(LocalForceField&&)      = default;

    void append(interaction_ptr&& interaction)
    {
        //XXX to reduce the number of LocalInteractions
        bool found = false;
        for(auto& item : interactions_)
        {
            if(typeid(*(item.get())) == typeid(*(interaction.get())))
            {
                std::cout << std::endl;
                item->append(std::move(interaction));
                found = true;
                break;
            }
        }
        if(not found)
        {
            interactions_.emplace_back(std::move(interaction));
        }
    }

    void calc_force(system_type& sys) const
    {
        for(const auto& item : this->interactions_)
            item->calc_force(sys);
        return;
    }
    real_type calc_energy(const system_type& sys) const
    {
        real_type energy = 0.0;
        for(const auto& item : this->interactions_)
        {
            energy += item->calc_energy(sys);
        }
        return energy;
    }

    std::string list_energy() const noexcept
    {
        std::string retval;
        for(const auto& i : interactions_)
        {
            retval += i->name();
            retval += ' ';
        }
        return retval;
    }

    std::string dump_energy(const system_type& sys) const noexcept
    {
        std::string retval;
        for(const auto& i : interactions_)
        {
            retval += std::to_string(i->calc_energy(sys));
            retval += ' ';
        }
        return retval;
    }

    iterator       begin()        noexcept {return interactions_.begin();}
    iterator       end()          noexcept {return interactions_.end();}
    const_iterator begin()  const noexcept {return interactions_.begin();}
    const_iterator end()    const noexcept {return interactions_.end();}
    const_iterator cbegin() const noexcept {return interactions_.begin();}
    const_iterator cend()   const noexcept {return interactions_.end();}

  private:

    container_type interactions_;
};

} // mjolnir
#endif /* MJOLNIR_LOCAL_FORCE_FIELD */
<commit_msg>remove needless output<commit_after>#ifndef MJOLNIR_LOCAL_FORCE_FIELD
#define MJOLNIR_LOCAL_FORCE_FIELD
#include "LocalInteractionBase.hpp"
#include <mjolnir/util/logger.hpp>
#include <utility>
#include <vector>
#include <array>
#include <memory>

namespace mjolnir
{

template<typename traitsT>
class LocalForceField
{
  public:
    typedef traitsT traits_type;
    typedef typename traits_type::real_type         real_type;
    typedef typename traits_type::coordinate_type   coordinate_type;
    typedef System<traits_type>                     system_type;
    typedef typename system_type::particle_type     particle_type;
    typedef LocalInteractionBase<traitsT>           interaction_type;
    typedef std::unique_ptr<interaction_type>       interaction_ptr;
    typedef std::vector<interaction_ptr>            container_type;
    typedef typename container_type::iterator       iterator;
    typedef typename container_type::const_iterator const_iterator;

  public:

    LocalForceField()  = default;
    ~LocalForceField() = default;
    LocalForceField(LocalForceField const&) = delete;
    LocalForceField(LocalForceField&&)      = default;
    LocalForceField& operator=(LocalForceField const&) = delete;
    LocalForceField& operator=(LocalForceField&&)      = default;

    void append(interaction_ptr&& interaction)
    {
        //XXX to reduce the number of LocalInteractions
        bool found = false;
        for(auto& item : interactions_)
        {
            if(typeid(*(item.get())) == typeid(*(interaction.get())))
            {
                item->append(std::move(interaction));
                found = true;
                break;
            }
        }
        if(not found)
        {
            interactions_.emplace_back(std::move(interaction));
        }
    }

    void calc_force(system_type& sys) const
    {
        for(const auto& item : this->interactions_)
            item->calc_force(sys);
        return;
    }
    real_type calc_energy(const system_type& sys) const
    {
        real_type energy = 0.0;
        for(const auto& item : this->interactions_)
        {
            energy += item->calc_energy(sys);
        }
        return energy;
    }

    std::string list_energy() const noexcept
    {
        std::string retval;
        for(const auto& i : interactions_)
        {
            retval += i->name();
            retval += ' ';
        }
        return retval;
    }

    std::string dump_energy(const system_type& sys) const noexcept
    {
        std::string retval;
        for(const auto& i : interactions_)
        {
            retval += std::to_string(i->calc_energy(sys));
            retval += ' ';
        }
        return retval;
    }

    iterator       begin()        noexcept {return interactions_.begin();}
    iterator       end()          noexcept {return interactions_.end();}
    const_iterator begin()  const noexcept {return interactions_.begin();}
    const_iterator end()    const noexcept {return interactions_.end();}
    const_iterator cbegin() const noexcept {return interactions_.begin();}
    const_iterator cend()   const noexcept {return interactions_.end();}

  private:

    container_type interactions_;
};

} // mjolnir
#endif /* MJOLNIR_LOCAL_FORCE_FIELD */
<|endoftext|>