<commit_before>#include <mex.h>

#include <cmath>
#include <iostream>
#include "drake/systems/plants/RigidBodyTree.h"
#include "drake/util/drakeMexUtil.h"
#include "drake/util/eigen_matrix_compare.h"
#include "drake/util/testUtil.h"

using namespace Eigen;
using namespace std;
using drake::util::MatrixCompareType;

/*
 * compares C++ robots generated via the matlab constructModelmex with the same
 * robot generated via the c++ parser
 */

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
  if (nrhs < 1) {
    mexErrMsgIdAndTxt(
        "Drake:compareParsersmex:NotEnoughInputs",
        "Usage compareParsersmex(model_ptr, urdf_file, floating_base_type)");
  }

  // first get the model_ptr back from matlab
  RigidBodyTree *matlab_model = (RigidBodyTree *)getDrakeMexPointer(prhs[0]);

  char urdf_file[1000];
  mxGetString(prhs[1], urdf_file, 1000);
  char floating_base_type_str[100] = "rpy";
  if (nrhs > 2) mxGetString(prhs[2], floating_base_type_str, 100);
  DrakeJoint::FloatingBaseType floating_base_type = DrakeJoint::QUATERNION;
  if (strcmp(floating_base_type_str, "fixed") == 0)
    floating_base_type = DrakeJoint::FIXED;
  else if (strcmp(floating_base_type_str, "rpy") == 0)
    floating_base_type = DrakeJoint::ROLLPITCHYAW;
  else if (strcmp(floating_base_type_str, "quat") == 0)
    floating_base_type = DrakeJoint::QUATERNION;
  else
    mexErrMsgIdAndTxt(
        "Drake:compareParsersmex:BadInputs",
        "Unknown floating base type.  must be 'fixed', 'rpy', or 'quat'");

  RigidBodyTree *cpp_model = new RigidBodyTree(urdf_file, floating_base_type);

  // Compute coordinate transform between the two models (in case they are not
  // identical)
  MatrixXd P = MatrixXd::Zero(cpp_model->num_positions,
                              matlab_model->num_positions);  // projection from
                                                             // the coordinates
                                                             // of matlab_model
                                                             // to cpp_model
  for (int i = 0; i < cpp_model->bodies.size(); i++) {
    if (cpp_model->bodies[i]->hasParent() &&
        cpp_model->bodies[i]->getJoint().getNumPositions() > 0) {
      RigidBody *b =
          matlab_model->findJoint(cpp_model->bodies[i]->getJoint().getName());
      if (b == nullptr) continue;
      for (int j = 0; j < b->getJoint().getNumPositions(); j++) {
        P(cpp_model->bodies[i]->position_num_start + j,
          b->position_num_start + j) = 1.0;
      }
    }
  }
  if (!P.isApprox(MatrixXd::Identity(matlab_model->num_positions,
                                     matlab_model->num_positions))) {
    cout << "P = \n" << P << endl;
    mexErrMsgTxt("ERROR: coordinates don't match");
  }

  std::default_random_engine generator;  // note: gets the same seed every time,
                                         // would have to seed it manually
  std::normal_distribution<double> distribution(0.0, 1.0);
  for (int trial = 0; trial < 1; trial++) {
    // generate random q
    VectorXd matlab_q = matlab_model->getRandomConfiguration(generator);
    VectorXd cpp_q(cpp_model->num_positions);
    cpp_q.noalias() = P * matlab_q;

    if ((matlab_model->num_positions != matlab_model->num_velocities) ||
        (cpp_model->num_positions != cpp_model->num_velocities)) {
      mexErrMsgTxt(
          "ERROR: num_positions!=num_velocities have to generate another P for "
          "this case");
    }

    // generate random v
    VectorXd matlab_v(matlab_model->num_velocities),
        cpp_v(cpp_model->num_velocities);
    for (int i = 0; i < matlab_model->num_velocities; i++)
      matlab_v[i] = distribution(generator);
    cpp_v.noalias() = P * matlab_v;

    // run kinematics
    KinematicsCache<double> matlab_cache =
        matlab_model->doKinematics(matlab_q, matlab_v, true);
    KinematicsCache<double> cpp_cache =
        cpp_model->doKinematics(cpp_q, cpp_v, true);

    {  // compare H, C, and B
      eigen_aligned_unordered_map<RigidBody const *,
                                  Matrix<double, TWIST_SIZE, 1> > f_ext;

      auto matlab_H = matlab_model->massMatrix(matlab_cache);
      auto cpp_H = cpp_model->massMatrix(cpp_cache);

      std::string explanation;
      if (!CompareMatrices(matlab_H, cpp_H, 1e-8, MatrixCompareType::absolute,
                           &explanation)) {
        throw std::runtime_error(
            "Drake: CompareParserMex: ERROR: H doesn't match: " + explanation);
      }

      auto matlab_C = matlab_model->dynamicsBiasTerm(matlab_cache, f_ext);
      auto cpp_C = cpp_model->dynamicsBiasTerm(cpp_cache, f_ext);

      if (!CompareMatrices(matlab_C, cpp_C, 1e-8, MatrixCompareType::absolute,
                           &explanation)) {
        throw std::runtime_error(
            "Drake: CompareParserMex: ERROR: C doesn't match: " + explanation);
      }

      if (!CompareMatrices(matlab_model->B, cpp_model->B, 1e-8,
                           MatrixCompareType::absolute, &explanation)) {
        throw std::runtime_error(
            "Drake: CompareParserMex: ERROR: B doesn't match: " + explanation);
      }
    }

    {  // compare joint limits
      std::string explanation;
      if (!CompareMatrices(matlab_model->joint_limit_min,
                           cpp_model->joint_limit_min, 1e-8,
                           MatrixCompareType::absolute, &explanation)) {
        throw std::runtime_error(
            "Drake: CompareParserMex: ERROR: joint_limit_min doesn't match: " +
            explanation);
      }

      if (!CompareMatrices(matlab_model->joint_limit_max,
                           cpp_model->joint_limit_max, 1e-8,
                           MatrixCompareType::absolute, &explanation)) {
        throw std::runtime_error(
            "Drake: CompareParserMex: ERROR: joint_limit_max doesn't match: " +
            explanation);
      }
    }

    {  // compare position constraints
      auto matlab_phi = matlab_model->positionConstraints(matlab_cache);
      auto cpp_phi = cpp_model->positionConstraints(cpp_cache);

      std::string explanation;
      if (!CompareMatrices(matlab_phi, cpp_phi, 1e-8,
                           MatrixCompareType::absolute, &explanation)) {
        throw std::runtime_error(
            "Drake: CompareParserMex: ERROR: phi doesn't match doesn't "
            "match: " +
            explanation);
      }

      auto matlab_dphi =
          matlab_model->positionConstraintsJacobian(matlab_cache);
      auto cpp_dphi = cpp_model->positionConstraintsJacobian(cpp_cache);
      if (!CompareMatrices(matlab_dphi, cpp_dphi, 1e-8,
                           MatrixCompareType::absolute, &explanation)) {
        throw std::runtime_error(
            "Drake: CompareParserMex: ERROR: dphi doesn't match: " +
            explanation);
      }
    }
  }

  delete cpp_model;
}
<commit_msg>clang-format on drake/systems/plants/test/compareParsersmex.cpp<commit_after>#include <mex.h>

#include <cmath>
#include <iostream>
#include "drake/systems/plants/RigidBodyTree.h"
#include "drake/util/drakeMexUtil.h"
#include "drake/util/eigen_matrix_compare.h"
#include "drake/util/testUtil.h"

using namespace Eigen;
using namespace std;
using drake::util::MatrixCompareType;

/*
 * compares C++ robots generated via the matlab constructModelmex with the same
 * robot generated via the c++ parser
 */

void mexFunction(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) {
  if (nrhs < 1) {
    mexErrMsgIdAndTxt(
        "Drake:compareParsersmex:NotEnoughInputs",
        "Usage compareParsersmex(model_ptr, urdf_file, floating_base_type)");
  }

  // first get the model_ptr back from matlab
  RigidBodyTree* matlab_model = (RigidBodyTree*)getDrakeMexPointer(prhs[0]);

  char urdf_file[1000];
  mxGetString(prhs[1], urdf_file, 1000);
  char floating_base_type_str[100] = "rpy";
  if (nrhs > 2) mxGetString(prhs[2], floating_base_type_str, 100);
  DrakeJoint::FloatingBaseType floating_base_type = DrakeJoint::QUATERNION;
  if (strcmp(floating_base_type_str, "fixed") == 0)
    floating_base_type = DrakeJoint::FIXED;
  else if (strcmp(floating_base_type_str, "rpy") == 0)
    floating_base_type = DrakeJoint::ROLLPITCHYAW;
  else if (strcmp(floating_base_type_str, "quat") == 0)
    floating_base_type = DrakeJoint::QUATERNION;
  else
    mexErrMsgIdAndTxt(
        "Drake:compareParsersmex:BadInputs",
        "Unknown floating base type.  must be 'fixed', 'rpy', or 'quat'");

  RigidBodyTree* cpp_model = new RigidBodyTree(urdf_file, floating_base_type);

  // Compute coordinate transform between the two models (in case they are not
  // identical)
  MatrixXd P = MatrixXd::Zero(cpp_model->num_positions,
                              matlab_model->num_positions);  // projection from
                                                             // the coordinates
                                                             // of matlab_model
                                                             // to cpp_model
  for (int i = 0; i < cpp_model->bodies.size(); i++) {
    if (cpp_model->bodies[i]->hasParent() &&
        cpp_model->bodies[i]->getJoint().getNumPositions() > 0) {
      RigidBody* b =
          matlab_model->findJoint(cpp_model->bodies[i]->getJoint().getName());
      if (b == nullptr) continue;
      for (int j = 0; j < b->getJoint().getNumPositions(); j++) {
        P(cpp_model->bodies[i]->position_num_start + j,
          b->position_num_start + j) = 1.0;
      }
    }
  }
  if (!P.isApprox(MatrixXd::Identity(matlab_model->num_positions,
                                     matlab_model->num_positions))) {
    cout << "P = \n" << P << endl;
    mexErrMsgTxt("ERROR: coordinates don't match");
  }

  std::default_random_engine generator;  // note: gets the same seed every time,
                                         // would have to seed it manually
  std::normal_distribution<double> distribution(0.0, 1.0);
  for (int trial = 0; trial < 1; trial++) {
    // generate random q
    VectorXd matlab_q = matlab_model->getRandomConfiguration(generator);
    VectorXd cpp_q(cpp_model->num_positions);
    cpp_q.noalias() = P * matlab_q;

    if ((matlab_model->num_positions != matlab_model->num_velocities) ||
        (cpp_model->num_positions != cpp_model->num_velocities)) {
      mexErrMsgTxt(
          "ERROR: num_positions!=num_velocities have to generate another P for "
          "this case");
    }

    // generate random v
    VectorXd matlab_v(matlab_model->num_velocities),
        cpp_v(cpp_model->num_velocities);
    for (int i = 0; i < matlab_model->num_velocities; i++)
      matlab_v[i] = distribution(generator);
    cpp_v.noalias() = P * matlab_v;

    // run kinematics
    KinematicsCache<double> matlab_cache =
        matlab_model->doKinematics(matlab_q, matlab_v, true);
    KinematicsCache<double> cpp_cache =
        cpp_model->doKinematics(cpp_q, cpp_v, true);

    {  // compare H, C, and B
      eigen_aligned_unordered_map<RigidBody const*,
                                  Matrix<double, TWIST_SIZE, 1>> f_ext;

      auto matlab_H = matlab_model->massMatrix(matlab_cache);
      auto cpp_H = cpp_model->massMatrix(cpp_cache);

      std::string explanation;
      if (!CompareMatrices(matlab_H, cpp_H, 1e-8, MatrixCompareType::absolute,
                           &explanation)) {
        throw std::runtime_error(
            "Drake: CompareParserMex: ERROR: H doesn't match: " + explanation);
      }

      auto matlab_C = matlab_model->dynamicsBiasTerm(matlab_cache, f_ext);
      auto cpp_C = cpp_model->dynamicsBiasTerm(cpp_cache, f_ext);

      if (!CompareMatrices(matlab_C, cpp_C, 1e-8, MatrixCompareType::absolute,
                           &explanation)) {
        throw std::runtime_error(
            "Drake: CompareParserMex: ERROR: C doesn't match: " + explanation);
      }

      if (!CompareMatrices(matlab_model->B, cpp_model->B, 1e-8,
                           MatrixCompareType::absolute, &explanation)) {
        throw std::runtime_error(
            "Drake: CompareParserMex: ERROR: B doesn't match: " + explanation);
      }
    }

    {  // compare joint limits
      std::string explanation;
      if (!CompareMatrices(matlab_model->joint_limit_min,
                           cpp_model->joint_limit_min, 1e-8,
                           MatrixCompareType::absolute, &explanation)) {
        throw std::runtime_error(
            "Drake: CompareParserMex: ERROR: joint_limit_min doesn't match: " +
            explanation);
      }

      if (!CompareMatrices(matlab_model->joint_limit_max,
                           cpp_model->joint_limit_max, 1e-8,
                           MatrixCompareType::absolute, &explanation)) {
        throw std::runtime_error(
            "Drake: CompareParserMex: ERROR: joint_limit_max doesn't match: " +
            explanation);
      }
    }

    {  // compare position constraints
      auto matlab_phi = matlab_model->positionConstraints(matlab_cache);
      auto cpp_phi = cpp_model->positionConstraints(cpp_cache);

      std::string explanation;
      if (!CompareMatrices(matlab_phi, cpp_phi, 1e-8,
                           MatrixCompareType::absolute, &explanation)) {
        throw std::runtime_error(
            "Drake: CompareParserMex: ERROR: phi doesn't match doesn't "
            "match: " +
            explanation);
      }

      auto matlab_dphi =
          matlab_model->positionConstraintsJacobian(matlab_cache);
      auto cpp_dphi = cpp_model->positionConstraintsJacobian(cpp_cache);
      if (!CompareMatrices(matlab_dphi, cpp_dphi, 1e-8,
                           MatrixCompareType::absolute, &explanation)) {
        throw std::runtime_error(
            "Drake: CompareParserMex: ERROR: dphi doesn't match: " +
            explanation);
      }
    }
  }

  delete cpp_model;
}
<|endoftext|>


<commit_before><commit_msg>show the control geometric propertis correctly (bnc#610921)<commit_after><|endoftext|>


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

#include "parser.hpp"

#include <iostream>

#include <pegtl.hh>
#include <pegtl/analyze.hh>
#include <pegtl/trace.hh>

using namespace pegtl;

namespace realm {
namespace parser {

// strings
struct unicode : list< seq< one< 'u' >, rep< 4, must< xdigit > > >, one< '\\' > > {};
struct escaped_char : one< '"', '\'', '\\', '/', 'b', 'f', 'n', 'r', 't', '0' > {};
struct escaped : sor< escaped_char, unicode > {};
struct unescaped : utf8::range< 0x20, 0x10FFFF > {};
struct chars : if_then_else< one< '\\' >, must< escaped >, unescaped > {};
struct dq_string_content : until< at< one< '"' > >, must< chars > > {};
struct dq_string : seq< one< '"' >, must< dq_string_content >, any > {};

struct sq_string_content : until< at< one< '\'' > >, must< chars > > {};
struct sq_string : seq< one< '\'' >, must< sq_string_content >, any > {};

// numbers
struct minus : opt< one< '-' > > {};
struct dot : one< '.' > {};

struct float_num : sor<
    seq< plus< digit >, dot, star< digit > >,
    seq< star< digit >, dot, plus< digit > >
> {};
struct hex_num : seq< one< '0' >, one< 'x', 'X' >, plus< xdigit > > {};
struct int_num : plus< digit > {};

struct number : seq< minus, sor< float_num, hex_num, int_num > > {};

struct true_value : pegtl_istring_t("true") {};
struct false_value : pegtl_istring_t("false") {};

// key paths
struct key_path : list< seq< sor< alpha, one< '_' > >, star< sor< alnum, one< '_', '-' > > > >, one< '.' > > {};

// argument
struct argument_index : plus< digit > {};
struct argument : seq< one< '$' >, must< argument_index > > {};

// expressions and operators
struct expr : sor< dq_string, sq_string, number, argument, true_value, false_value, key_path > {};

struct eq : sor< two< '=' >, one< '=' > > {};
struct noteq : pegtl::string< '!', '=' > {};
struct lteq : pegtl::string< '<', '=' > {};
struct lt : one< '<' > {};
struct gteq : pegtl::string< '>', '=' > {};
struct gt : one< '>' > {};
struct contains : pegtl_istring_t("contains") {};
struct begins : pegtl_istring_t("beginswith") {};
struct ends : pegtl_istring_t("endswith") {};

template<typename A, typename B>
struct pad_plus : seq< plus< B >, A, plus< B > > {};

struct padded_oper : pad_plus< sor< contains, begins, ends >, blank > {};
struct symbolic_oper : pad< sor< eq, noteq, lteq, lt, gteq, gt >, blank > {};

// predicates
struct comparison_pred : seq< expr, sor< padded_oper, symbolic_oper >, expr > {};

struct pred;
struct group_pred : if_must< one< '(' >, pad< pred, blank >, one< ')' > > {};
struct true_pred : pegtl_istring_t("truepredicate") {};
struct false_pred : pegtl_istring_t("falsepredicate") {};

struct not_pre : seq< sor< one< '!' >, pegtl_istring_t("not") > > {};
struct atom_pred : seq< opt< not_pre >, pad< sor< group_pred, true_pred, false_pred, comparison_pred >, blank > > {};

struct and_op : pad< sor< two< '&' >, pegtl_istring_t("and") >, blank > {};
struct or_op : pad< sor< two< '|' >, pegtl_istring_t("or") >, blank > {};

struct or_ext : if_must< or_op, pred > {};
struct and_ext : if_must< and_op, pred > {};
struct and_pred : seq< atom_pred, star< and_ext > > {};

struct pred : seq< and_pred, star< or_ext > > {};

// state
struct ParserState
{
    std::vector<Predicate *> predicate_stack;
    Predicate &current() {
        return *predicate_stack.back();
    }

    bool negate_next = false;

    void addExpression(Expression && exp)
    {
        if (current().type == Predicate::Type::Comparison) {
            current().cmpr.expr[1] = std::move(exp);
            predicate_stack.pop_back();
        }
        else {
            Predicate p(Predicate::Type::Comparison);
            p.cmpr.expr[0] = std::move(exp);
            if (negate_next) {
                p.negate = true;
                negate_next = false;
            }
            current().cpnd.sub_predicates.emplace_back(std::move(p));
            predicate_stack.push_back(&current().cpnd.sub_predicates.back());
        }
    }
};

// rules
template< typename Rule >
struct action : nothing< Rule > {};

#ifdef REALM_PARSER_PRINT_TOKENS
    #define DEBUG_PRINT_TOKEN(string) std::cout << string << std::endl
#else
    #define DEBUG_PRINT_TOKEN(string)
#endif

template<> struct action< and_ext >
{
    static void apply( const input & in, ParserState & state )
    {
        DEBUG_PRINT_TOKEN("<and>");

        // if we were put into an OR group we need to rearrange
        auto &current = state.current();
        if (current.type == Predicate::Type::Or) {
            auto &sub_preds = current.cpnd.sub_predicates;
            auto &second_last = sub_preds[sub_preds.size()-2];
            if (second_last.type == Predicate::Type::And) {
                // if we are in an OR group and second to last predicate group is
                // an AND group then move the last predicate inside
                second_last.cpnd.sub_predicates.push_back(std::move(sub_preds.back()));
                sub_preds.pop_back();
            }
            else {
                // otherwise combine last two into a new AND group
                Predicate pred(Predicate::Type::And);
                pred.cpnd.sub_predicates.emplace_back(std::move(second_last));
                pred.cpnd.sub_predicates.emplace_back(std::move(sub_preds.back()));
                sub_preds.pop_back();
                sub_preds.pop_back();
                sub_preds.push_back(std::move(pred));
            }
        }
    }
};

template<> struct action< or_ext >
{
    static void apply( const input & in, ParserState & state )
    {
        DEBUG_PRINT_TOKEN("<or>");

        // if already an OR group do nothing
        auto &current = state.current();
        if (current.type == Predicate::Type::Or) {
            return;
        }

        // if only two predicates in the group, then convert to OR
        auto &sub_preds = state.current().cpnd.sub_predicates;
        if (sub_preds.size()) {
            current.type = Predicate::Type::Or;
            return;
        }

        // split the current group into to groups which are ORed together
        Predicate pred1(Predicate::Type::And), pred2(Predicate::Type::And);
        pred1.cpnd.sub_predicates.insert(sub_preds.begin(), sub_preds.back());
        pred2.cpnd.sub_predicates.push_back(std::move(sub_preds.back()));

        current.type = Predicate::Type::Or;
        sub_preds.clear();
        sub_preds.emplace_back(std::move(pred1));
        sub_preds.emplace_back(std::move(pred2));
    }
};

#define EXPRESSION_ACTION(rule, type)                               \
template<> struct action< rule > {                                  \
    static void apply( const input & in, ParserState & state ) {    \
        DEBUG_PRINT_TOKEN(in.string());                             \
        state.addExpression(Expression(type, in.string())); }};

EXPRESSION_ACTION(dq_string_content, Expression::Type::String)
EXPRESSION_ACTION(sq_string_content, Expression::Type::String)
EXPRESSION_ACTION(key_path, Expression::Type::KeyPath)
EXPRESSION_ACTION(number, Expression::Type::Number)
EXPRESSION_ACTION(true_value, Expression::Type::True)
EXPRESSION_ACTION(false_value, Expression::Type::False)
EXPRESSION_ACTION(argument_index, Expression::Type::Argument)

template<> struct action< true_pred >
{
    static void apply( const input & in, ParserState & state )
    {
        DEBUG_PRINT_TOKEN(in.string());
        state.current().cpnd.sub_predicates.emplace_back(Predicate::Type::True);
    }
};

template<> struct action< false_pred >
{
    static void apply( const input & in, ParserState & state )
    {
        DEBUG_PRINT_TOKEN(in.string());
        state.current().cpnd.sub_predicates.emplace_back(Predicate::Type::False);
    }
};

#define OPERATOR_ACTION(rule, oper)                                 \
template<> struct action< rule > {                                  \
    static void apply( const input & in, ParserState & state ) {    \
        DEBUG_PRINT_TOKEN(in.string());                             \
        state.current().cmpr.op = oper; }};

OPERATOR_ACTION(eq, Predicate::Operator::Equal)
OPERATOR_ACTION(noteq, Predicate::Operator::NotEqual)
OPERATOR_ACTION(gteq, Predicate::Operator::GreaterThanOrEqual)
OPERATOR_ACTION(gt, Predicate::Operator::GreaterThan)
OPERATOR_ACTION(lteq, Predicate::Operator::LessThanOrEqual)
OPERATOR_ACTION(lt, Predicate::Operator::LessThan)
OPERATOR_ACTION(begins, Predicate::Operator::BeginsWith)
OPERATOR_ACTION(ends, Predicate::Operator::EndsWith)
OPERATOR_ACTION(contains, Predicate::Operator::Contains)

template<> struct action< one< '(' > >
{
    static void apply( const input & in, ParserState & state )
    {
        DEBUG_PRINT_TOKEN("<begin_group>");

        Predicate group(Predicate::Type::And);
        if (state.negate_next) {
            group.negate = true;
            state.negate_next = false;
        }

        state.current().cpnd.sub_predicates.emplace_back(std::move(group));
        state.predicate_stack.push_back(&state.current().cpnd.sub_predicates.back());
    }
};

template<> struct action< group_pred >
{
    static void apply( const input & in, ParserState & state )
    {
        DEBUG_PRINT_TOKEN("<end_group>");
        state.predicate_stack.pop_back();
    }
};

template<> struct action< not_pre >
{
    static void apply( const input & in, ParserState & state )
    {
        DEBUG_PRINT_TOKEN("<not>");
        state.negate_next = true;
    }
};

template< typename Rule >
struct error_message_control : pegtl::normal< Rule >
{
    static const std::string error_message;

    template< typename Input, typename ... States >
    static void raise( const Input & in, States && ... )
    {
        throw pegtl::parse_error( error_message, in );
    }
};

template<>
const std::string error_message_control< chars >::error_message = "Invalid characters in string constant.";

template< typename Rule>
const std::string error_message_control< Rule >::error_message = "Invalid predicate.";

Predicate parse(const std::string &query)
{
    Predicate out_predicate(Predicate::Type::And);

    ParserState state;
    state.predicate_stack.push_back(&out_predicate);

    pegtl::parse< must< pred, eof >, action, error_message_control >(query, query, state);
    if (out_predicate.type == Predicate::Type::And && out_predicate.cpnd.sub_predicates.size() == 1) {
        return std::move(out_predicate.cpnd.sub_predicates.back());
    }
    return std::move(out_predicate);
}

void analyzeGrammar()
{
    analyze<pred>();
}

}}

<commit_msg>fix for mixed && and || queries<commit_after>////////////////////////////////////////////////////////////////////////////
//
// Copyright 2015 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////

#include "parser.hpp"

#include <iostream>

#include <pegtl.hh>
#include <pegtl/analyze.hh>
#include <pegtl/trace.hh>

using namespace pegtl;

namespace realm {
namespace parser {

// strings
struct unicode : list< seq< one< 'u' >, rep< 4, must< xdigit > > >, one< '\\' > > {};
struct escaped_char : one< '"', '\'', '\\', '/', 'b', 'f', 'n', 'r', 't', '0' > {};
struct escaped : sor< escaped_char, unicode > {};
struct unescaped : utf8::range< 0x20, 0x10FFFF > {};
struct chars : if_then_else< one< '\\' >, must< escaped >, unescaped > {};
struct dq_string_content : until< at< one< '"' > >, must< chars > > {};
struct dq_string : seq< one< '"' >, must< dq_string_content >, any > {};

struct sq_string_content : until< at< one< '\'' > >, must< chars > > {};
struct sq_string : seq< one< '\'' >, must< sq_string_content >, any > {};

// numbers
struct minus : opt< one< '-' > > {};
struct dot : one< '.' > {};

struct float_num : sor<
    seq< plus< digit >, dot, star< digit > >,
    seq< star< digit >, dot, plus< digit > >
> {};
struct hex_num : seq< one< '0' >, one< 'x', 'X' >, plus< xdigit > > {};
struct int_num : plus< digit > {};

struct number : seq< minus, sor< float_num, hex_num, int_num > > {};

struct true_value : pegtl_istring_t("true") {};
struct false_value : pegtl_istring_t("false") {};

// key paths
struct key_path : list< seq< sor< alpha, one< '_' > >, star< sor< alnum, one< '_', '-' > > > >, one< '.' > > {};

// argument
struct argument_index : plus< digit > {};
struct argument : seq< one< '$' >, must< argument_index > > {};

// expressions and operators
struct expr : sor< dq_string, sq_string, number, argument, true_value, false_value, key_path > {};

struct eq : sor< two< '=' >, one< '=' > > {};
struct noteq : pegtl::string< '!', '=' > {};
struct lteq : pegtl::string< '<', '=' > {};
struct lt : one< '<' > {};
struct gteq : pegtl::string< '>', '=' > {};
struct gt : one< '>' > {};
struct contains : pegtl_istring_t("contains") {};
struct begins : pegtl_istring_t("beginswith") {};
struct ends : pegtl_istring_t("endswith") {};

template<typename A, typename B>
struct pad_plus : seq< plus< B >, A, plus< B > > {};

struct padded_oper : pad_plus< sor< contains, begins, ends >, blank > {};
struct symbolic_oper : pad< sor< eq, noteq, lteq, lt, gteq, gt >, blank > {};

// predicates
struct comparison_pred : seq< expr, sor< padded_oper, symbolic_oper >, expr > {};

struct pred;
struct group_pred : if_must< one< '(' >, pad< pred, blank >, one< ')' > > {};
struct true_pred : pegtl_istring_t("truepredicate") {};
struct false_pred : pegtl_istring_t("falsepredicate") {};

struct not_pre : seq< sor< one< '!' >, pegtl_istring_t("not") > > {};
struct atom_pred : seq< opt< not_pre >, pad< sor< group_pred, true_pred, false_pred, comparison_pred >, blank > > {};

struct and_op : pad< sor< two< '&' >, pegtl_istring_t("and") >, blank > {};
struct or_op : pad< sor< two< '|' >, pegtl_istring_t("or") >, blank > {};

struct or_ext : if_must< or_op, pred > {};
struct and_ext : if_must< and_op, pred > {};
struct and_pred : seq< atom_pred, star< and_ext > > {};

struct pred : seq< and_pred, star< or_ext > > {};

// state
struct ParserState
{
    std::vector<Predicate *> predicate_stack;
    Predicate &current()
    {
        return *predicate_stack.back();
    }

    bool current_is_compound()
    {
        return current().type == Predicate::Type::And || current().type == Predicate::Type::Or;
    }

    bool negate_next = false;

    void addExpression(Expression && exp)
    {
        Predicate &cur = current();
        if (cur.type == Predicate::Type::Comparison) {
            cur.cmpr.expr[1] = std::move(exp);
            predicate_stack.pop_back();
        }
        else {
            assert(current_is_compound());

            Predicate p(Predicate::Type::Comparison);
            p.cmpr.expr[0] = std::move(exp);
            if (negate_next) {
                p.negate = true;
                negate_next = false;
            }

            cur.cpnd.sub_predicates.emplace_back(std::move(p));
            predicate_stack.push_back(&cur.cpnd.sub_predicates.back());
        }
    }
};

// rules
template< typename Rule >
struct action : nothing< Rule > {};

#ifdef REALM_PARSER_PRINT_TOKENS
    #define DEBUG_PRINT_TOKEN(string) std::cout << string << std::endl
#else
    #define DEBUG_PRINT_TOKEN(string)
#endif

template<> struct action< and_ext >
{
    static void apply( const input & in, ParserState & state )
    {
        DEBUG_PRINT_TOKEN("<and>");
        assert(state.current_is_compound());

        // if we were put into an OR group we need to rearrange
        auto &current = state.current();
        if (current.type == Predicate::Type::Or) {
            auto &sub_preds = current.cpnd.sub_predicates;
            auto &second_last = sub_preds[sub_preds.size()-2];
            if (second_last.type == Predicate::Type::And) {
                // if we are in an OR group and second to last predicate group is
                // an AND group then move the last predicate inside
                second_last.cpnd.sub_predicates.push_back(std::move(sub_preds.back()));
                sub_preds.pop_back();
            }
            else {
                // otherwise combine last two into a new AND group
                Predicate pred(Predicate::Type::And);
                pred.cpnd.sub_predicates.emplace_back(std::move(second_last));
                pred.cpnd.sub_predicates.emplace_back(std::move(sub_preds.back()));
                sub_preds.pop_back();
                sub_preds.pop_back();
                sub_preds.push_back(std::move(pred));
            }
        }
    }
};

template<> struct action< or_ext >
{
    static void apply( const input & in, ParserState & state )
    {
        DEBUG_PRINT_TOKEN("<or>");
        assert(state.current_is_compound());

        // if already an OR group do nothing
        auto &current = state.current();
        if (current.type == Predicate::Type::Or) {
            return;
        }

        // if only two predicates in the group, then convert to OR
        auto &sub_preds = state.current().cpnd.sub_predicates;
        assert(sub_preds.size() > 1);
        if (sub_preds.size() == 2) {
            current.type = Predicate::Type::Or;
            return;
        }

        // split the current group into to groups which are ORed together
        Predicate pred1(Predicate::Type::And), pred2(Predicate::Type::And);
        std::vector<Predicate>::iterator second_last = sub_preds.end() - 2;
        pred1.cpnd.sub_predicates.insert(pred1.cpnd.sub_predicates.begin(), sub_preds.begin(), second_last);
        pred2.cpnd.sub_predicates.insert(pred2.cpnd.sub_predicates.begin(), second_last, sub_preds.end());

        current.type = Predicate::Type::Or;
        sub_preds.clear();
        sub_preds.emplace_back(std::move(pred1));
        sub_preds.emplace_back(std::move(pred2));
    }
};

#define EXPRESSION_ACTION(rule, type)                               \
template<> struct action< rule > {                                  \
    static void apply( const input & in, ParserState & state ) {    \
        DEBUG_PRINT_TOKEN(in.string());                             \
        state.addExpression(Expression(type, in.string())); }};

EXPRESSION_ACTION(dq_string_content, Expression::Type::String)
EXPRESSION_ACTION(sq_string_content, Expression::Type::String)
EXPRESSION_ACTION(key_path, Expression::Type::KeyPath)
EXPRESSION_ACTION(number, Expression::Type::Number)
EXPRESSION_ACTION(true_value, Expression::Type::True)
EXPRESSION_ACTION(false_value, Expression::Type::False)
EXPRESSION_ACTION(argument_index, Expression::Type::Argument)

template<> struct action< true_pred >
{
    static void apply( const input & in, ParserState & state )
    {
        DEBUG_PRINT_TOKEN(in.string());
        state.current().cpnd.sub_predicates.emplace_back(Predicate::Type::True);
    }
};

template<> struct action< false_pred >
{
    static void apply( const input & in, ParserState & state )
    {
        DEBUG_PRINT_TOKEN(in.string());
        state.current().cpnd.sub_predicates.emplace_back(Predicate::Type::False);
    }
};

#define OPERATOR_ACTION(rule, oper)                                 \
template<> struct action< rule > {                                  \
    static void apply( const input & in, ParserState & state ) {    \
        DEBUG_PRINT_TOKEN(in.string());                             \
        state.current().cmpr.op = oper; }};

OPERATOR_ACTION(eq, Predicate::Operator::Equal)
OPERATOR_ACTION(noteq, Predicate::Operator::NotEqual)
OPERATOR_ACTION(gteq, Predicate::Operator::GreaterThanOrEqual)
OPERATOR_ACTION(gt, Predicate::Operator::GreaterThan)
OPERATOR_ACTION(lteq, Predicate::Operator::LessThanOrEqual)
OPERATOR_ACTION(lt, Predicate::Operator::LessThan)
OPERATOR_ACTION(begins, Predicate::Operator::BeginsWith)
OPERATOR_ACTION(ends, Predicate::Operator::EndsWith)
OPERATOR_ACTION(contains, Predicate::Operator::Contains)

template<> struct action< one< '(' > >
{
    static void apply( const input & in, ParserState & state )
    {
        DEBUG_PRINT_TOKEN("<begin_group>");

        Predicate group(Predicate::Type::And);
        if (state.negate_next) {
            group.negate = true;
            state.negate_next = false;
        }

        state.current().cpnd.sub_predicates.emplace_back(std::move(group));
        state.predicate_stack.push_back(&state.current().cpnd.sub_predicates.back());
    }
};

template<> struct action< group_pred >
{
    static void apply( const input & in, ParserState & state )
    {
        DEBUG_PRINT_TOKEN("<end_group>");
        state.predicate_stack.pop_back();
    }
};

template<> struct action< not_pre >
{
    static void apply( const input & in, ParserState & state )
    {
        DEBUG_PRINT_TOKEN("<not>");
        state.negate_next = true;
    }
};

template< typename Rule >
struct error_message_control : pegtl::normal< Rule >
{
    static const std::string error_message;

    template< typename Input, typename ... States >
    static void raise( const Input & in, States && ... )
    {
        throw pegtl::parse_error( error_message, in );
    }
};

template<>
const std::string error_message_control< chars >::error_message = "Invalid characters in string constant.";

template< typename Rule>
const std::string error_message_control< Rule >::error_message = "Invalid predicate.";

Predicate parse(const std::string &query)
{
    Predicate out_predicate(Predicate::Type::And);

    ParserState state;
    state.predicate_stack.push_back(&out_predicate);

    pegtl::parse< must< pred, eof >, action, error_message_control >(query, query, state);
    if (out_predicate.type == Predicate::Type::And && out_predicate.cpnd.sub_predicates.size() == 1) {
        return std::move(out_predicate.cpnd.sub_predicates.back());
    }
    return std::move(out_predicate);
}

void analyzeGrammar()
{
    analyze<pred>();
}

}}

<|endoftext|>


<commit_before>/* Copyright 2013 Paulo Roberto Urio <paulourio@gmail.com> */
#include "./acs.h"

namespace acs {

ACSEdgeDetection::ACSEdgeDetection(cv::Mat input, GUIController controller) :
		input_(input), pheromone_(input.rows, input.cols, CV_8UC1), controller_(
				controller) {
}

ACSEdgeDetection::~ACSEdgeDetection() {
}

void ACSEdgeDetection::Compute() {
}

}  // namespace acs
<commit_msg>Inicializando a matriz de feromônio com 0.0001<commit_after>/* Copyright 2013 Paulo Roberto Urio <paulourio@gmail.com> */
#include "./acs.h"

namespace acs {

ACSEdgeDetection::ACSEdgeDetection(cv::Mat input, GUIController controller) :
		input_(input), pheromone_(input.rows, input.cols, CV_32FC1), controller_(
				controller) {
	pheromone_ = 0.0001f;
}

ACSEdgeDetection::~ACSEdgeDetection() {
}

void ACSEdgeDetection::Compute() {
}

}  // namespace acs
<|endoftext|>


<commit_before>/*-
 * Copyright (c) 2012, Achilleas Margaritis
 * Copyright (c) 2014, David T. Chisnall
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
#ifndef PEGMATITE_AST_HPP
#define PEGMATITE_AST_HPP

#include <cassert>
#include <list>
#include <unordered_map>
#include <memory>
#include "parser.hh"

namespace pegmatite {

class ASTNode;
template <class T, bool OPT> class ASTPtr;
template <class T> class ASTList;
template <class T> class BindAST;

/** type of AST node stack.
 */
typedef std::vector<std::unique_ptr<ASTNode>> ASTStack;

#ifdef USE_RTTI
#define PEGMATITE_RTTI(thisclass, superclass)
#else
/**
 * Define the methods required for pegmatite's lightweight RTTI replacement to
 * work.  This should be used at the end of the class definition and will
 * provide support for safe downcasting.
 */
#define PEGMATITE_RTTI(thisclass, superclass)             \
	friend ASTNode;                                      \
protected:                                               \
	virtual char *kind()                                 \
	{                                                    \
		return thisclass::classKind();                   \
	}                                                    \
	static char *classKind()                             \
	{                                                    \
		static char thisclass ## id;                     \
		return &thisclass ## id;                         \
	}                                                    \
public:                                                  \
	virtual bool isa(char *x)                            \
	{                                                    \
		return (x == kind()) ||                          \
				(superclass::isa(x));                    \
	}
#endif

/**
 * Base class for AST nodes.
 */
class ASTNode
{
public:
	/**
	 * Constructs the AST node, with a null parent.
	 */
	ASTNode() : parent_node(0) {}
	/**
	 * Copying AST nodes is not supported.
	 */
	ASTNode(const ASTNode&) = delete;

	/**
	 * Destructor does nothing, virtual for subclasses to use.
	 */
	virtual ~ASTNode() {}

	/**
	 * Returns the parent of this AST node, or `nullptr` if there isn't one
	 * (either if this is the root, or if it is still in the stack waiting to
	 * be added to the tree).
	 */
	ASTNode *parent() const { return parent_node; }

	/**
	 * Interface for constructing the AST node.  The input range `r` is the
	 * range within the source.
	 */
	virtual void construct(const InputRange &r, ASTStack &st) {}

private:
	/**
	 * The parent AST node.
	 */
	ASTNode *parent_node;

	template <class T, bool OPT> friend class ASTPtr;
	template <class T> friend class ASTList;
	template <class T> friend class BindAST;

#ifndef USE_RTTI
protected:
	/**
	 * Returns the kind of object class.  This is a unique pointer that can be
	 * tested against pointers returned by classKind() to determine whether
	 * they can be safely compared.
	 */
	virtual char *kind() { return classKind(); }
	/**
	 * Returns the unique identifier for this class.
	 */
	static char *classKind()
	{
		static char ASTNodeid;
		return &ASTNodeid;
	}
public:
	/**
	 * Root implementation of the RTTI-replacement for builds not wishing to
	 * use RTTI.  This returns true if `x` is the value returned from
	 * `classKind()`, or false otherwise.
	 */
	virtual bool isa(char *x)
	{
		return x == classKind();
	}
	/**
	 * Returns true if this object is an instance of `T`.  Note that this
	 * *only* works with single-inheritance hierarchies.  If you wish to use
	 * multiple inheritance in your AST classes, then you must define
	 * `USE_RTTI` and use the C++ RTTI mechanism.
	 */
	template <class T> bool isa()
	{
		return isa(T::classKind());
	}
	/**
	 * Returns a pointer to this object as a pointer to a child class, or
	 * `nullptr` if the cast would be unsafe.
	 *
	 * Note that AST nodes are intended to be always used as unique pointers
	 * and so the returned object is *only* valid as long as the unique pointer
	 * is valid.
	 */
	template <class T> T* get_as()
	{
		return this ? (isa<T>() ? static_cast<T*>(this) : nullptr) : nullptr;
	}
#else
public:
	template <class T> T* get_as()
	{
		return dynamic_cast<T*>(this);
	}
#endif
};

class ASTMember;

/** type of ast member vector.
 */

/**
 * The base class for non-leaf AST nodes.  Subclasses can have instances of
 * `ASTMember` subclasses as fields and will automatically construct them.
 */
class ASTContainer : public ASTNode
{
public:
	/**
	 * Constructs the container, setting a thread-local value to point to it
	 * allowing constructors in fields of the subclass to register themselves
	 * in the members vector.
	 */
	ASTContainer();

	/**
	 * Asks all members to construct themselves from the stack. The members are
	 * asked to construct themselves in reverse order from a node stack (`st`).
	 *
	 * The input range (`r`) is unused, because the leaf nodes have already
	 * constructed themselves at this point.
	 */
	virtual void construct(const InputRange &r, ASTStack &st);

private:
	/**
	 * The type used for tracking the fields of subclasses.
	 */
	typedef std::vector<ASTMember *> ASTMember_vector;
	/**
	 * References to all of the fields of the subclass that will be
	 * automatically constructed.
	 */
	ASTMember_vector members;

	friend class ASTMember;
	PEGMATITE_RTTI(ASTContainer, ASTNode)
};

/**
 * Base class for children of `ASTContainer`.
 */
class ASTMember
{
public:
	/**
	 * On construction, `ASTMember` sets its `container_node` field to the
	 * `ASTContainer` currently under construction and registers itself with
	 * the container, to be notified during the construction phase.
	 */
	ASTMember();

	/**
	 * Returns the container of which this object is a field.
	 */
	ASTContainer *container() const { return container_node; }

	/**
	 * Interface for constructing references to AST objects from the stack.
	 */
	virtual void construct(ASTStack &st) = 0;
protected:
	/**
	 * The container that owns this object.
	 */
	ASTContainer *container_node;
};

/**
 * An `ASTPtr` is a wrapper around a pointer to an AST object.  It is intended
 * to be a member of an `ASTContainer` and will automatically pop the top item
 * from the stack and claim it when building the AST..
 */
template <class T, bool OPT = false> class ASTPtr : public ASTMember
{
public:
	/**
	 * Constructs the object in the
	 */
	ASTPtr() : ptr(nullptr) {}

	/** gets the underlying ptr value.
		@return the underlying ptr value.
	 */
	T *get() const
	{
		return ptr.get();
	}

	/** auto conversion to the underlying object ptr.
		@return the underlying ptr value.
	 */
	const std::unique_ptr<T> &operator *() const
	{
		return ptr;
	}

	/** member access.
		@return the underlying ptr value.
	 */
	const std::unique_ptr<T> &operator ->() const
	{
		assert(ptr);
		return ptr;
	}

	/**
	 * Pops the next matching object from the AST stack `st` and claims it.
	 */
	virtual void construct(ASTStack &st)
	{
		assert(!st.empty() && "Stack must not be empty");
		//get the node
		ASTNode *node = st.back().get();

		//get the object
		T *obj = node->get_as<T>();

		assert((obj || OPT) && "Required objects must exist!");
		//if the object is optional, simply return
		if (OPT && !obj)
		{
			return;
		}
		//set the new object
		ptr.reset(obj);
		//pop the node from the stack
		st.back().release();
		st.pop_back();
		ptr->parent_node = container_node;
	}

private:
	/**
	 * The node that we are pointing to.
	 */
	std::unique_ptr<T> ptr;
};

/** A list of objects.
	It pops objects of the given type from the ast stack, until no more objects can be popped.
	It assumes ownership of objects.
	@param T type of object to control.
 */
template <class T> class ASTList : public ASTMember
{
public:
	///list type.
	typedef std::list<std::unique_ptr<T>> container;

	///the default constructor.
	ASTList() {}

	/** duplicates the objects of the given list.
		@param src source object.
	 */
	ASTList(const ASTList<T> &src)
	{
		_dup(src);
	}

	/** returns the container of objects.
		@return the container of objects.
	 */
	const container &objects() const
	{
		return child_objects;
	}

	/**
	 * Pops objects of type T from the stack (`st`) until no more objects can
	 * be popped.
	 */
	virtual void construct(ASTStack &st)
	{
		for(;;)
		{
			//if the stack is empty
			if (st.empty()) break;

			//get the node
			ASTNode *node = st.back().get();

			//get the object
			T *obj = node->get_as<T>();

			//if the object was not not of the appropriate type,
			//end the list parsing
			if (!obj) return;

			//remove the node from the stack
			st.back().release();
			st.pop_back();

			//insert the object in the list, in reverse order
			child_objects.push_front(std::unique_ptr<T>(obj));

			//set the object's parent
			obj->parent_node = ASTMember::container();
		}
	}

private:
	//objects
	container child_objects;

	//duplicate the given list.
	void _dup(const ASTList<T> &src)
	{
		for (auto child : src.child_objects)
		{
			T *obj = new T(child.get());
			child_objects.push_back(obj);
			obj->parent_node = ASTMember::container();
		}
	}
};

/** parses the given input.
	@param i input.
	@param g root rule of grammar.
	@param ws whitespace rule.
	@param el list of errors.
	@param d user data, passed to the parse procedures.
	@return pointer to ast node created, or null if there was an error.
		The return object must be deleted by the caller.
 */
std::unique_ptr<ASTNode> parse(Input &i, const Rule &g, const Rule &ws,
                               ErrorList &el, const ParserDelegate &d);

/**
 * A parser delegate that is responsible for creating AST nodes from the input.
 *
 * This class manages a mapping from rules in some grammar to AST nodes.
 * Instances of the `BindAST` class that are fields of a subclass of this will
 * automatically register rules on creation.
 *
 * The recommended use for this class is to only register rules on construction
 * (either explicitly in the constructor or implicitly via `BindAST` members).
 * This will give a completely reentrant delegate, which can be used by
 * multiple threads to parse multiple inputs safely.
 */
class ASTParserDelegate : ParserDelegate
{
	/**
	 * BindAST is a friend so that it can call the `set_parse_proc()` function,
	 * which should never be called from anything else.
	 */
	template <class T> friend class BindAST;
	private:
	/**
	 * The map from rules to parsing handlers.
	 */
	std::unordered_map<const Rule*, parse_proc> handlers;
	/**
	 * Registers a callback in this delegate.  This should only be called from
	 * the `static` version of this function.
	 */
	void set_parse_proc(const Rule &r, parse_proc p);
	/**
	 * Registers a callback for a specific rule in the instance of this class
	 * currently under construction in this thread.  This should only ever be
	 * called by `BindAST` instances.
	 */
	static void bind_parse_proc(const Rule &r, parse_proc p);
	public:
	/**
	 * Default constructor, registers this class in thread-local storage so
	 * that it can be referenced by BindAST fields in subclasses when their
	 * constructors are run.
	 */
	ASTParserDelegate();
	virtual parse_proc get_parse_proc(const Rule &) const;
	/**
	 * Parse an input `i`, starting from rule `g` in the grammar for which
	 * this is a delegate.  The rule `ws` is used as whitespace.  Errors are
	 * returned via the `el` parameter and the root of the AST via the `ast`
	 * parameter.
	 *
	 * This function returns true on a successful parse, or false otherwise.
	 */
	template <class T> bool parse(Input &i, const Rule &g, const Rule &ws,
	                              ErrorList &el, std::unique_ptr<T> &ast) const
	{
		std::unique_ptr<ASTNode> node = pegmatite::parse(i, g, ws, el, *this);
		T *n = node->get_as<T>();
		if (n)
		{
			node.release();
			ast.reset(n);
			return true;
		}
		return false;
	}
};

/**
 * The `BindAST` class is responsible for
 */
template <class T> class BindAST
{
public:
	/**
	 * Bind the AST class described in the
	 */
	BindAST(const Rule &r)
	{
		ASTParserDelegate::bind_parse_proc(r, [](const ParserPosition &b,
		                                         const ParserPosition &e, void *d)
			{
				ASTStack *st = reinterpret_cast<ASTStack *>(d);
				T *obj = new T();
				obj->construct(InputRange(b, e), *st);
				st->push_back(std::unique_ptr<ASTNode>(obj));
			});
	}
};

} //namespace pegmatite

#endif //PEGMATITE_AST_HPP
<commit_msg>Improve some more comments.<commit_after>/*-
 * Copyright (c) 2012, Achilleas Margaritis
 * Copyright (c) 2014, David T. Chisnall
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
#ifndef PEGMATITE_AST_HPP
#define PEGMATITE_AST_HPP

#include <cassert>
#include <list>
#include <unordered_map>
#include <memory>
#include "parser.hh"

namespace pegmatite {

class ASTNode;
template <class T, bool OPT> class ASTPtr;
template <class T> class ASTList;
template <class T> class BindAST;

/** type of AST node stack.
 */
typedef std::vector<std::unique_ptr<ASTNode>> ASTStack;

#ifdef USE_RTTI
#define PEGMATITE_RTTI(thisclass, superclass)
#else
/**
 * Define the methods required for pegmatite's lightweight RTTI replacement to
 * work.  This should be used at the end of the class definition and will
 * provide support for safe downcasting.
 */
#define PEGMATITE_RTTI(thisclass, superclass)             \
	friend ASTNode;                                      \
protected:                                               \
	virtual char *kind()                                 \
	{                                                    \
		return thisclass::classKind();                   \
	}                                                    \
	static char *classKind()                             \
	{                                                    \
		static char thisclass ## id;                     \
		return &thisclass ## id;                         \
	}                                                    \
public:                                                  \
	virtual bool isa(char *x)                            \
	{                                                    \
		return (x == kind()) ||                          \
				(superclass::isa(x));                    \
	}
#endif

/**
 * Base class for AST nodes.
 */
class ASTNode
{
public:
	/**
	 * Constructs the AST node, with a null parent.
	 */
	ASTNode() : parent_node(0) {}
	/**
	 * Copying AST nodes is not supported.
	 */
	ASTNode(const ASTNode&) = delete;

	/**
	 * Destructor does nothing, virtual for subclasses to use.
	 */
	virtual ~ASTNode() {}

	/**
	 * Returns the parent of this AST node, or `nullptr` if there isn't one
	 * (either if this is the root, or if it is still in the stack waiting to
	 * be added to the tree).
	 */
	ASTNode *parent() const { return parent_node; }

	/**
	 * Interface for constructing the AST node.  The input range `r` is the
	 * range within the source.
	 */
	virtual void construct(const InputRange &r, ASTStack &st) {}

private:
	/**
	 * The parent AST node.
	 */
	ASTNode *parent_node;

	template <class T, bool OPT> friend class ASTPtr;
	template <class T> friend class ASTList;
	template <class T> friend class BindAST;

#ifndef USE_RTTI
protected:
	/**
	 * Returns the kind of object class.  This is a unique pointer that can be
	 * tested against pointers returned by classKind() to determine whether
	 * they can be safely compared.
	 */
	virtual char *kind() { return classKind(); }
	/**
	 * Returns the unique identifier for this class.
	 */
	static char *classKind()
	{
		static char ASTNodeid;
		return &ASTNodeid;
	}
public:
	/**
	 * Root implementation of the RTTI-replacement for builds not wishing to
	 * use RTTI.  This returns true if `x` is the value returned from
	 * `classKind()`, or false otherwise.
	 */
	virtual bool isa(char *x)
	{
		return x == classKind();
	}
	/**
	 * Returns true if this object is an instance of `T`.  Note that this
	 * *only* works with single-inheritance hierarchies.  If you wish to use
	 * multiple inheritance in your AST classes, then you must define
	 * `USE_RTTI` and use the C++ RTTI mechanism.
	 */
	template <class T> bool isa()
	{
		return isa(T::classKind());
	}
	/**
	 * Returns a pointer to this object as a pointer to a child class, or
	 * `nullptr` if the cast would be unsafe.
	 *
	 * Note that AST nodes are intended to be always used as unique pointers
	 * and so the returned object is *only* valid as long as the unique pointer
	 * is valid.
	 */
	template <class T> T* get_as()
	{
		return this ? (isa<T>() ? static_cast<T*>(this) : nullptr) : nullptr;
	}
#else
public:
	template <class T> T* get_as()
	{
		return dynamic_cast<T*>(this);
	}
#endif
};

class ASTMember;

/** type of ast member vector.
 */

/**
 * The base class for non-leaf AST nodes.  Subclasses can have instances of
 * `ASTMember` subclasses as fields and will automatically construct them.
 */
class ASTContainer : public ASTNode
{
public:
	/**
	 * Constructs the container, setting a thread-local value to point to it
	 * allowing constructors in fields of the subclass to register themselves
	 * in the members vector.
	 */
	ASTContainer();

	/**
	 * Asks all members to construct themselves from the stack. The members are
	 * asked to construct themselves in reverse order from a node stack (`st`).
	 *
	 * The input range (`r`) is unused, because the leaf nodes have already
	 * constructed themselves at this point.
	 */
	virtual void construct(const InputRange &r, ASTStack &st);

private:
	/**
	 * The type used for tracking the fields of subclasses.
	 */
	typedef std::vector<ASTMember *> ASTMember_vector;
	/**
	 * References to all of the fields of the subclass that will be
	 * automatically constructed.
	 */
	ASTMember_vector members;

	friend class ASTMember;
	PEGMATITE_RTTI(ASTContainer, ASTNode)
};

/**
 * Base class for children of `ASTContainer`.
 */
class ASTMember
{
public:
	/**
	 * On construction, `ASTMember` sets its `container_node` field to the
	 * `ASTContainer` currently under construction and registers itself with
	 * the container, to be notified during the construction phase.
	 */
	ASTMember();

	/**
	 * Returns the container of which this object is a field.
	 */
	ASTContainer *container() const { return container_node; }

	/**
	 * Interface for constructing references to AST objects from the stack.
	 */
	virtual void construct(ASTStack &st) = 0;
protected:
	/**
	 * The container that owns this object.
	 */
	ASTContainer *container_node;
};

/**
 * An `ASTPtr` is a wrapper around a pointer to an AST object.  It is intended
 * to be a member of an `ASTContainer` and will automatically pop the top item
 * from the stack and claim it when building the AST..
 */
template <class T, bool OPT = false> class ASTPtr : public ASTMember
{
public:
	/**
	 * Constructs the object in the
	 */
	ASTPtr() : ptr(nullptr) {}

	/** gets the underlying ptr value.
		@return the underlying ptr value.
	 */
	T *get() const
	{
		return ptr.get();
	}

	/** auto conversion to the underlying object ptr.
		@return the underlying ptr value.
	 */
	const std::unique_ptr<T> &operator *() const
	{
		return ptr;
	}

	/** member access.
		@return the underlying ptr value.
	 */
	const std::unique_ptr<T> &operator ->() const
	{
		assert(ptr);
		return ptr;
	}

	/**
	 * Pops the next matching object from the AST stack `st` and claims it.
	 */
	virtual void construct(ASTStack &st)
	{
		assert(!st.empty() && "Stack must not be empty");
		//get the node
		ASTNode *node = st.back().get();

		//get the object
		T *obj = node->get_as<T>();

		assert((obj || OPT) && "Required objects must exist!");
		//if the object is optional, simply return
		if (OPT && !obj)
		{
			return;
		}
		//set the new object
		ptr.reset(obj);
		//pop the node from the stack
		st.back().release();
		st.pop_back();
		ptr->parent_node = container_node;
	}

private:
	/**
	 * The node that we are pointing to.
	 */
	std::unique_ptr<T> ptr;
};

/** A list of objects.
	It pops objects of the given type from the ast stack, until no more objects can be popped.
	It assumes ownership of objects.
	@param T type of object to control.
 */
template <class T> class ASTList : public ASTMember
{
public:
	///list type.
	typedef std::list<std::unique_ptr<T>> container;

	///the default constructor.
	ASTList() {}

	/** duplicates the objects of the given list.
		@param src source object.
	 */
	ASTList(const ASTList<T> &src)
	{
		_dup(src);
	}

	/** returns the container of objects.
		@return the container of objects.
	 */
	const container &objects() const
	{
		return child_objects;
	}

	/**
	 * Pops objects of type T from the stack (`st`) until no more objects can
	 * be popped.
	 */
	virtual void construct(ASTStack &st)
	{
		for(;;)
		{
			//if the stack is empty
			if (st.empty()) break;

			//get the node
			ASTNode *node = st.back().get();

			//get the object
			T *obj = node->get_as<T>();

			//if the object was not not of the appropriate type,
			//end the list parsing
			if (!obj) return;

			//remove the node from the stack
			st.back().release();
			st.pop_back();

			//insert the object in the list, in reverse order
			child_objects.push_front(std::unique_ptr<T>(obj));

			//set the object's parent
			obj->parent_node = ASTMember::container();
		}
	}

private:
	//objects
	container child_objects;

	//duplicate the given list.
	void _dup(const ASTList<T> &src)
	{
		for (auto child : src.child_objects)
		{
			T *obj = new T(child.get());
			child_objects.push_back(obj);
			obj->parent_node = ASTMember::container();
		}
	}
};

/** parses the given input.
	@param i input.
	@param g root rule of grammar.
	@param ws whitespace rule.
	@param el list of errors.
	@param d user data, passed to the parse procedures.
	@return pointer to ast node created, or null if there was an error.
		The return object must be deleted by the caller.
 */
std::unique_ptr<ASTNode> parse(Input &i, const Rule &g, const Rule &ws,
                               ErrorList &el, const ParserDelegate &d);

/**
 * A parser delegate that is responsible for creating AST nodes from the input.
 *
 * This class manages a mapping from rules in some grammar to AST nodes.
 * Instances of the `BindAST` class that are fields of a subclass of this will
 * automatically register rules on creation.
 *
 * The recommended use for this class is to only register rules on construction
 * (either explicitly in the constructor or implicitly via `BindAST` members).
 * This will give a completely reentrant delegate, which can be used by
 * multiple threads to parse multiple inputs safely.
 */
class ASTParserDelegate : ParserDelegate
{
	/**
	 * BindAST is a friend so that it can call the `set_parse_proc()` function,
	 * which should never be called from anything else.
	 */
	template <class T> friend class BindAST;
	private:
	/**
	 * The map from rules to parsing handlers.
	 */
	std::unordered_map<const Rule*, parse_proc> handlers;
	/**
	 * Registers a callback in this delegate.  This should only be called from
	 * the `static` version of this function.
	 */
	void set_parse_proc(const Rule &r, parse_proc p);
	/**
	 * Registers a callback for a specific rule in the instance of this class
	 * currently under construction in this thread.  This should only ever be
	 * called by `BindAST` instances.
	 */
	static void bind_parse_proc(const Rule &r, parse_proc p);
	public:
	/**
	 * Default constructor, registers this class in thread-local storage so
	 * that it can be referenced by BindAST fields in subclasses when their
	 * constructors are run.
	 */
	ASTParserDelegate();
	virtual parse_proc get_parse_proc(const Rule &) const;
	/**
	 * Parse an input `i`, starting from rule `g` in the grammar for which
	 * this is a delegate.  The rule `ws` is used as whitespace.  Errors are
	 * returned via the `el` parameter and the root of the AST via the `ast`
	 * parameter.
	 *
	 * This function returns true on a successful parse, or false otherwise.
	 */
	template <class T> bool parse(Input &i, const Rule &g, const Rule &ws,
	                              ErrorList &el, std::unique_ptr<T> &ast) const
	{
		std::unique_ptr<ASTNode> node = pegmatite::parse(i, g, ws, el, *this);
		T *n = node->get_as<T>();
		if (n)
		{
			node.release();
			ast.reset(n);
			return true;
		}
		return false;
	}
};

/**
 * The `BindAST` class is responsible for
 * The `BindAST` class is responsible for binding an action to a rule.  The
 * template argument is the `ASTNode` subclass representing the action.  Its
 * `construct()` method will be called when the rule is matched.
 */
template <class T> class BindAST
{
public:
	/**
	 * Bind the AST class described in the grammar to the rule specified.
	 */
	BindAST(const Rule &r)
	{
		ASTParserDelegate::bind_parse_proc(r, [](const ParserPosition &b,
		                                         const ParserPosition &e, void *d)
			{
				ASTStack *st = reinterpret_cast<ASTStack *>(d);
				T *obj = new T();
				obj->construct(InputRange(b, e), *st);
				st->push_back(std::unique_ptr<ASTNode>(obj));
			});
	}
};

} //namespace pegmatite

#endif //PEGMATITE_AST_HPP
<|endoftext|>


<commit_before><commit_msg>passing by reference<commit_after><|endoftext|>


<commit_before>#include "config.h"
#include <cstdlib>
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <cstring>

using namespace std;

//// parameters

// for bam file
int min_flank_length = 5;
int min_clip_length = 5;
int32_t average_read_length = 100;
int32_t min_bundle_gap = 50;
int min_num_hits_in_bundle = 20;
int32_t min_splice_boundary_hits = 1;
uint32_t min_mapping_quality = 1;
double max_indel_ratio = 0.2;
int32_t min_subregion_gap = 3;
int32_t min_subregion_length = 15;
double min_subregion_overlap = 2;
double min_average_overlap = 3.0;
int min_max_region_overlap = 5;
double min_region_coverage = 0.5;
int max_num_bundles = -1;
int tail_coverage = 8;
int slope_bin_size = 10;
int slope_bin_num = 30;
int slope_min_score = 1000;
double slope_min_sigma = 5.0;
int pseudo_length_count = 10;
bool use_paired_end = false;
int max_equations_each_iteration = 50;
double max_ignorable_edge_weight = 10.0;
double max_removable_edge_weight = 5.5;
double min_edge_weight = 1.9;
double min_coverage = 10.0;
int min_boundary_length = 80;
int min_boundary_score = 1000;
double min_boundary_sigma = 4.0;
int32_t partial_exon_length = 100;

// for algorithm
double join_min_reliability = 0.6;
double infer_min_reliability = 0.6;
double infer_root_reliability = 0.4;
int max_dp_table_size = 10000;
int max_num_subsetsum_solutions = 10;
double max_equation_error_ratio = 0.1;
double max_split_error_ratio = 0.1;
double max_router_error_ratio = 0.3;
int min_router_count = 1;
double min_boundary_edge_weight_ratio = 0.05;
double transcript_min_expression = 1.0;
int min_hyper_edges_count = 20;
bool strand_reverse = false;
bool ignore_single_exon_transcripts = false;

// for simulation
int simulation_num_vertices = 0;
int simulation_num_edges = 0;
int simulation_max_edge_weight = 0;

//// from command line
string algo = "shao";
string input_file;
string ref_file;
string ref_file1;
string ref_file2;
string output_file;

bool output_tex_files = false;
string fixed_gene_name = "";
int min_gtf_transcripts_num = 0;
bool fast_mode = true;

int print_parameters()
{
	// for bam file
	printf("parameters:\n");
	printf("min_flank_length = %d\n", min_flank_length);
	printf("min_clip_length = %d\n", min_clip_length);
	printf("min_bundle_gap = %d\n", min_bundle_gap);
	printf("min_subregion_gap = %d\n", min_subregion_gap);
	printf("min_num_hits_in_bundle = %d\n", min_num_hits_in_bundle);
	printf("min_splice_boundary_hits = %d\n", min_splice_boundary_hits);
	printf("min_mapping_quality = %d\n", min_mapping_quality);
	printf("min_average_overlap = %.2lf\n", min_average_overlap);
	printf("min_subregion_overlap = %.2lf\n", min_subregion_overlap);
	printf("max_indel_ratio = %.2lf\n", max_indel_ratio);
	printf("min_subregion_length = %d\n", min_subregion_length);
	printf("min_max_region_overlap = %d\n", min_max_region_overlap);
	printf("min_region_coverage = %.2lf\n", min_region_coverage);
	printf("max_num_bundles = %d\n", max_num_bundles);
	printf("tail_coverage = %d\n", tail_coverage);
	printf("use_paired_end = %c\n", use_paired_end ? 'T' : 'F');
	printf("slope_bin_size = %d\n", slope_bin_size);
	printf("slope_bin_num = %d\n", slope_bin_num);
	printf("slope_min_score = %d\n", slope_min_score);
	printf("slope_min_sigma = %.2lf\n", slope_min_sigma);
	printf("average_read_length = %d\n", average_read_length);
	printf("pseudo_length_count = %d\n", pseudo_length_count);
	printf("strand_reverse = %c\n", strand_reverse ? 'T' : 'F');
	printf("ignore_single_exon_transcripts = %c\n", ignore_single_exon_transcripts ? 'T' : 'F');
	printf("max_ignorable_edge_weight = %.2lf\n", max_ignorable_edge_weight);
	printf("max_removable_edge_weight = %.2lf\n", max_removable_edge_weight);
	printf("min_edge_weight = %.2lf\n", min_edge_weight);
	printf("min_coverage = %.2lf\n", min_coverage);
	printf("min_boundary_length = %d\n", min_boundary_length);
	printf("min_boundary_score = %d\n", min_boundary_score);
	printf("min_boundary_signma = %.2lf\n", min_boundary_sigma);
	printf("partial_exon_length = %d\n", partial_exon_length);

	// for algorithm
	printf("join_min_reliability = %.2lf\n", join_min_reliability);
	printf("infer_min_reliability = %.2lf\n", infer_min_reliability);
	printf("infer_root_reliability = %.2lf\n", infer_root_reliability);
	printf("max_dp_table_size = %d\n", max_dp_table_size);
	printf("max_num_subsetsum_solutions = %d\n", max_num_subsetsum_solutions);
	printf("max_equation_error_ratio = %.2lf\n", max_equation_error_ratio);
	printf("max_split_error_ratio = %.2lf\n", max_split_error_ratio);
	printf("max_router_error_ratio = %.2lf\n", max_router_error_ratio);
	printf("min_router_count = %d\n", min_router_count);
	printf("min_boundary_edge_weight_ratio = %.2lf\n", min_boundary_edge_weight_ratio);
	printf("transcript_min_expression = %.2lf\n", transcript_min_expression);
	printf("min_hyper_edges_count = %d\n", min_hyper_edges_count);
	printf("max_equations_each_iteration = %d\n", max_equations_each_iteration);

	// for simulation
	printf("simulation_num_vertices = %d\n", simulation_num_vertices);
	printf("simulation_num_edges = %d\n", simulation_num_edges);
	printf("simulation_max_edge_weight = %d\n", simulation_max_edge_weight);

	// for command
	printf("algo = %s\n", algo.c_str());
	printf("input_file = %s\n", input_file.c_str());
	printf("ref_file = %s\n", ref_file.c_str());
	printf("ref_file1 = %s\n", ref_file1.c_str());
	printf("ref_file2 = %s\n", ref_file2.c_str());
	printf("output_file = %s\n", output_file.c_str());
	printf("output_tex_files = %c\n", output_tex_files ? 'T' : 'F');
	printf("fixed_gene_name = %s\n", fixed_gene_name.c_str());
	printf("min_gtf_transcripts_num = %d\n", min_gtf_transcripts_num);
	printf("fast_mode = %c\n", fast_mode ? 'T' : 'F');
	printf("\n");

	return 0;
}

bool parse_arguments(int argc, const char ** argv)
{
	output_tex_files = false;
	bool b = false;
	for(int i = 1; i < argc; i++)
	{
		if(string(argv[i]) == "-a")
		{
			algo = string(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "-i")
		{
			input_file = string(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "-o")
		{
			output_file = string(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "-r")
		{
			ref_file = string(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "-r1")
		{
			ref_file1 = string(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "-r2")
		{
			ref_file2 = string(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "-g")
		{
			fixed_gene_name = string(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "-t")
		{
			output_tex_files = true;
		}
		else if(string(argv[i]) == "-p")
		{
			use_paired_end = true;
		}
		else if(string(argv[i]) == "-RF")
		{
			strand_reverse = true;
		}
		else if(string(argv[i]) == "-m")
		{
			ignore_single_exon_transcripts = true;
		}
		else if(string(argv[i]) == "-x")
		{
			min_edge_weight = atof(argv[i + 1]);
			i++;
		}
	}

	return b;
}
<commit_msg>set default min_edeg_weight to 2.9<commit_after>#include "config.h"
#include <cstdlib>
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <cstring>

using namespace std;

//// parameters

// for bam file
int min_flank_length = 5;
int min_clip_length = 5;
int32_t average_read_length = 100;
int32_t min_bundle_gap = 50;
int min_num_hits_in_bundle = 20;
int32_t min_splice_boundary_hits = 1;
uint32_t min_mapping_quality = 1;
double max_indel_ratio = 0.2;
int32_t min_subregion_gap = 3;
int32_t min_subregion_length = 15;
double min_subregion_overlap = 2;
double min_average_overlap = 3.0;
int min_max_region_overlap = 5;
double min_region_coverage = 0.5;
int max_num_bundles = -1;
int tail_coverage = 8;
int slope_bin_size = 10;
int slope_bin_num = 30;
int slope_min_score = 1000;
double slope_min_sigma = 5.0;
int pseudo_length_count = 10;
bool use_paired_end = false;
int max_equations_each_iteration = 50;
double max_ignorable_edge_weight = 10.0;
double max_removable_edge_weight = 5.5;
double min_edge_weight = 2.9;
double min_coverage = 10.0;
int min_boundary_length = 80;
int min_boundary_score = 1000;
double min_boundary_sigma = 4.0;
int32_t partial_exon_length = 100;

// for algorithm
double join_min_reliability = 0.6;
double infer_min_reliability = 0.6;
double infer_root_reliability = 0.4;
int max_dp_table_size = 10000;
int max_num_subsetsum_solutions = 10;
double max_equation_error_ratio = 0.1;
double max_split_error_ratio = 0.1;
double max_router_error_ratio = 0.3;
int min_router_count = 1;
double min_boundary_edge_weight_ratio = 0.05;
double transcript_min_expression = 1.0;
int min_hyper_edges_count = 20;
bool strand_reverse = false;
bool ignore_single_exon_transcripts = false;

// for simulation
int simulation_num_vertices = 0;
int simulation_num_edges = 0;
int simulation_max_edge_weight = 0;

//// from command line
string algo = "shao";
string input_file;
string ref_file;
string ref_file1;
string ref_file2;
string output_file;

bool output_tex_files = false;
string fixed_gene_name = "";
int min_gtf_transcripts_num = 0;
bool fast_mode = true;

int print_parameters()
{
	// for bam file
	printf("parameters:\n");
	printf("min_flank_length = %d\n", min_flank_length);
	printf("min_clip_length = %d\n", min_clip_length);
	printf("min_bundle_gap = %d\n", min_bundle_gap);
	printf("min_subregion_gap = %d\n", min_subregion_gap);
	printf("min_num_hits_in_bundle = %d\n", min_num_hits_in_bundle);
	printf("min_splice_boundary_hits = %d\n", min_splice_boundary_hits);
	printf("min_mapping_quality = %d\n", min_mapping_quality);
	printf("min_average_overlap = %.2lf\n", min_average_overlap);
	printf("min_subregion_overlap = %.2lf\n", min_subregion_overlap);
	printf("max_indel_ratio = %.2lf\n", max_indel_ratio);
	printf("min_subregion_length = %d\n", min_subregion_length);
	printf("min_max_region_overlap = %d\n", min_max_region_overlap);
	printf("min_region_coverage = %.2lf\n", min_region_coverage);
	printf("max_num_bundles = %d\n", max_num_bundles);
	printf("tail_coverage = %d\n", tail_coverage);
	printf("use_paired_end = %c\n", use_paired_end ? 'T' : 'F');
	printf("slope_bin_size = %d\n", slope_bin_size);
	printf("slope_bin_num = %d\n", slope_bin_num);
	printf("slope_min_score = %d\n", slope_min_score);
	printf("slope_min_sigma = %.2lf\n", slope_min_sigma);
	printf("average_read_length = %d\n", average_read_length);
	printf("pseudo_length_count = %d\n", pseudo_length_count);
	printf("strand_reverse = %c\n", strand_reverse ? 'T' : 'F');
	printf("ignore_single_exon_transcripts = %c\n", ignore_single_exon_transcripts ? 'T' : 'F');
	printf("max_ignorable_edge_weight = %.2lf\n", max_ignorable_edge_weight);
	printf("max_removable_edge_weight = %.2lf\n", max_removable_edge_weight);
	printf("min_edge_weight = %.2lf\n", min_edge_weight);
	printf("min_coverage = %.2lf\n", min_coverage);
	printf("min_boundary_length = %d\n", min_boundary_length);
	printf("min_boundary_score = %d\n", min_boundary_score);
	printf("min_boundary_signma = %.2lf\n", min_boundary_sigma);
	printf("partial_exon_length = %d\n", partial_exon_length);

	// for algorithm
	printf("join_min_reliability = %.2lf\n", join_min_reliability);
	printf("infer_min_reliability = %.2lf\n", infer_min_reliability);
	printf("infer_root_reliability = %.2lf\n", infer_root_reliability);
	printf("max_dp_table_size = %d\n", max_dp_table_size);
	printf("max_num_subsetsum_solutions = %d\n", max_num_subsetsum_solutions);
	printf("max_equation_error_ratio = %.2lf\n", max_equation_error_ratio);
	printf("max_split_error_ratio = %.2lf\n", max_split_error_ratio);
	printf("max_router_error_ratio = %.2lf\n", max_router_error_ratio);
	printf("min_router_count = %d\n", min_router_count);
	printf("min_boundary_edge_weight_ratio = %.2lf\n", min_boundary_edge_weight_ratio);
	printf("transcript_min_expression = %.2lf\n", transcript_min_expression);
	printf("min_hyper_edges_count = %d\n", min_hyper_edges_count);
	printf("max_equations_each_iteration = %d\n", max_equations_each_iteration);

	// for simulation
	printf("simulation_num_vertices = %d\n", simulation_num_vertices);
	printf("simulation_num_edges = %d\n", simulation_num_edges);
	printf("simulation_max_edge_weight = %d\n", simulation_max_edge_weight);

	// for command
	printf("algo = %s\n", algo.c_str());
	printf("input_file = %s\n", input_file.c_str());
	printf("ref_file = %s\n", ref_file.c_str());
	printf("ref_file1 = %s\n", ref_file1.c_str());
	printf("ref_file2 = %s\n", ref_file2.c_str());
	printf("output_file = %s\n", output_file.c_str());
	printf("output_tex_files = %c\n", output_tex_files ? 'T' : 'F');
	printf("fixed_gene_name = %s\n", fixed_gene_name.c_str());
	printf("min_gtf_transcripts_num = %d\n", min_gtf_transcripts_num);
	printf("fast_mode = %c\n", fast_mode ? 'T' : 'F');
	printf("\n");

	return 0;
}

bool parse_arguments(int argc, const char ** argv)
{
	output_tex_files = false;
	bool b = false;
	for(int i = 1; i < argc; i++)
	{
		if(string(argv[i]) == "-a")
		{
			algo = string(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "-i")
		{
			input_file = string(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "-o")
		{
			output_file = string(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "-r")
		{
			ref_file = string(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "-r1")
		{
			ref_file1 = string(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "-r2")
		{
			ref_file2 = string(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "-g")
		{
			fixed_gene_name = string(argv[i + 1]);
			i++;
		}
		else if(string(argv[i]) == "-t")
		{
			output_tex_files = true;
		}
		else if(string(argv[i]) == "-p")
		{
			use_paired_end = true;
		}
		else if(string(argv[i]) == "-RF")
		{
			strand_reverse = true;
		}
		else if(string(argv[i]) == "-m")
		{
			ignore_single_exon_transcripts = true;
		}
		else if(string(argv[i]) == "-x")
		{
			min_edge_weight = atof(argv[i + 1]);
			i++;
		}
	}

	return b;
}
<|endoftext|>


<commit_before>/**
* Client Key Exchange Message
* (C) 2004-2008 Jack Lloyd
*
* Released under the terms of the Botan license
*/

#include <botan/tls_messages.h>
#include <botan/dh.h>
#include <botan/rsa.h>
#include <botan/rng.h>
#include <botan/look_pk.h>
#include <botan/loadstor.h>
#include <memory>

namespace Botan {

/**
* Create a new Client Key Exchange message
*/
Client_Key_Exchange::Client_Key_Exchange(RandomNumberGenerator& rng,
                                         Record_Writer& writer,
                                         HandshakeHash& hash,
                                         const Public_Key* pub_key,
                                         Version_Code using_version,
                                         Version_Code pref_version)
   {
   const DH_PublicKey* dh_pub = dynamic_cast<const DH_PublicKey*>(pub_key);
   const RSA_PublicKey* rsa_pub = dynamic_cast<const RSA_PublicKey*>(pub_key);

   include_length = true;

   if(dh_pub)
      {
      DH_PrivateKey priv_key(rng, dh_pub->get_domain());
      pre_master = priv_key.derive_key(dh_pub->get_y());
      key_material = priv_key.public_value();
      }
   else if(rsa_pub)
      {
      pre_master.resize(48);
      rng.randomize(pre_master, 48);
      pre_master[0] = (pref_version >> 8) & 0xFF;
      pre_master[1] = (pref_version     ) & 0xFF;

      std::auto_ptr<PK_Encryptor> encryptor(get_pk_encryptor(*rsa_pub,
                                                             "PKCS1v15"));

      key_material = encryptor->encrypt(pre_master, rng);

      if(using_version == SSL_V3)
         include_length = false;
      }
   else
      throw Invalid_Argument("Client_Key_Exchange: Key not RSA or DH");

   send(writer, hash);
   }

/**
* Read a Client Key Exchange message
*/
Client_Key_Exchange::Client_Key_Exchange(const MemoryRegion<byte>& contents,
                                         const CipherSuite& suite,
                                         Version_Code using_version)
   {
   include_length = true;

   if(using_version == SSL_V3 &&
      (suite.kex_type() == CipherSuite::NO_KEX ||
       suite.kex_type() == CipherSuite::RSA_KEX))
      include_length = false;

   deserialize(contents);
   }

/**
* Serialize a Client Key Exchange message
*/
SecureVector<byte> Client_Key_Exchange::serialize() const
   {
   SecureVector<byte> buf;

   if(include_length)
      {
      u16bit key_size = key_material.size();
      buf.append(get_byte(0, key_size));
      buf.append(get_byte(1, key_size));
      }
   buf.append(key_material);

   return buf;
   }

/**
* Deserialize a Client Key Exchange message
*/
void Client_Key_Exchange::deserialize(const MemoryRegion<byte>& buf)
   {
   if(include_length)
      {
      if(buf.size() < 2)
         throw Decoding_Error("Client_Key_Exchange: Packet corrupted");

      u32bit size = make_u16bit(buf[0], buf[1]);
      if(size + 2 != buf.size())
         throw Decoding_Error("Client_Key_Exchange: Packet corrupted");

      key_material.set(buf + 2, size);
      }
   else
      key_material = buf;
   }

/**
* Return the pre_master_secret
*/
SecureVector<byte>
Client_Key_Exchange::pre_master_secret(RandomNumberGenerator& rng,
                                       const Private_Key* priv_key,
                                       Version_Code version)
   {
   const DH_PrivateKey* dh_priv = dynamic_cast<const DH_PrivateKey*>(priv_key);
   const RSA_PrivateKey* rsa_priv =
      dynamic_cast<const RSA_PrivateKey*>(priv_key);

   if(dh_priv)
      {
      try {
         pre_master = dh_priv->derive_key(key_material, key_material.size());
      }
      catch(...)
         {
         pre_master.resize(dh_priv->public_value().size());
         rng.randomize(pre_master, pre_master.size());
         }

      return pre_master;
      }
   else if(rsa_priv)
      {
      std::auto_ptr<PK_Decryptor> decryptor(get_pk_decryptor(*rsa_priv,
                                                             "PKCS1v15"));

      try {
         pre_master = decryptor->decrypt(key_material);

         if(pre_master.size() != 48 ||
            make_u16bit(pre_master[0], pre_master[1]) != version)
            throw Decoding_Error("Client_Key_Exchange: Secret corrupted");
      }
      catch(std::exception)
         {
         pre_master.resize(48);
         rng.randomize(pre_master, pre_master.size());
         pre_master[0] = (version >> 8) & 0xFF;
         pre_master[1] = (version     ) & 0xFF;
         }

      return pre_master;
      }
   else
      throw Invalid_Argument("Client_Key_Exchange: Bad key for decrypt");
   }

/**
* Return the pre_master_secret
*/
SecureVector<byte> Client_Key_Exchange::pre_master_secret() const
   {
   return pre_master;
   }

}
<commit_msg>Client_Key_Exchange needs modification for DH changes<commit_after>/**
* Client Key Exchange Message
* (C) 2004-2010 Jack Lloyd
*
* Released under the terms of the Botan license
*/

#include <botan/tls_messages.h>
#include <botan/dh.h>
#include <botan/rsa.h>
#include <botan/rng.h>
#include <botan/look_pk.h>
#include <botan/loadstor.h>
#include <memory>

namespace Botan {

/**
* Create a new Client Key Exchange message
*/
Client_Key_Exchange::Client_Key_Exchange(RandomNumberGenerator& rng,
                                         Record_Writer& writer,
                                         HandshakeHash& hash,
                                         const Public_Key* pub_key,
                                         Version_Code using_version,
                                         Version_Code pref_version)
   {
   include_length = true;

   if(const DH_PublicKey* dh_pub = dynamic_cast<const DH_PublicKey*>(pub_key))
      {
      DH_PrivateKey priv_key(rng, dh_pub->get_domain());

      std::auto_ptr<PK_Key_Agreement> ka(get_pk_kas(priv_key, "Raw"));

      pre_master = ka->derive_key(0, dh_pub->public_value()).bits_of();

      key_material = priv_key.public_value();
      }
   else if(const RSA_PublicKey* rsa_pub = dynamic_cast<const RSA_PublicKey*>(pub_key))
      {
      pre_master.resize(48);
      rng.randomize(pre_master, 48);
      pre_master[0] = (pref_version >> 8) & 0xFF;
      pre_master[1] = (pref_version     ) & 0xFF;

      std::auto_ptr<PK_Encryptor> encryptor(get_pk_encryptor(*rsa_pub,
                                                             "PKCS1v15"));

      key_material = encryptor->encrypt(pre_master, rng);

      if(using_version == SSL_V3)
         include_length = false;
      }
   else
      throw Invalid_Argument("Client_Key_Exchange: Key not RSA or DH");

   send(writer, hash);
   }

/**
* Read a Client Key Exchange message
*/
Client_Key_Exchange::Client_Key_Exchange(const MemoryRegion<byte>& contents,
                                         const CipherSuite& suite,
                                         Version_Code using_version)
   {
   include_length = true;

   if(using_version == SSL_V3 &&
      (suite.kex_type() == CipherSuite::NO_KEX ||
       suite.kex_type() == CipherSuite::RSA_KEX))
      include_length = false;

   deserialize(contents);
   }

/**
* Serialize a Client Key Exchange message
*/
SecureVector<byte> Client_Key_Exchange::serialize() const
   {
   SecureVector<byte> buf;

   if(include_length)
      {
      u16bit key_size = key_material.size();
      buf.append(get_byte(0, key_size));
      buf.append(get_byte(1, key_size));
      }
   buf.append(key_material);

   return buf;
   }

/**
* Deserialize a Client Key Exchange message
*/
void Client_Key_Exchange::deserialize(const MemoryRegion<byte>& buf)
   {
   if(include_length)
      {
      if(buf.size() < 2)
         throw Decoding_Error("Client_Key_Exchange: Packet corrupted");

      u32bit size = make_u16bit(buf[0], buf[1]);
      if(size + 2 != buf.size())
         throw Decoding_Error("Client_Key_Exchange: Packet corrupted");

      key_material.set(buf + 2, size);
      }
   else
      key_material = buf;
   }

/**
* Return the pre_master_secret
*/
SecureVector<byte>
Client_Key_Exchange::pre_master_secret(RandomNumberGenerator& rng,
                                       const Private_Key* priv_key,
                                       Version_Code version)
   {

   if(const DH_PrivateKey* dh_priv = dynamic_cast<const DH_PrivateKey*>(priv_key))
      {
      try {
         std::auto_ptr<PK_Key_Agreement> ka(get_pk_kas(*dh_priv, "Raw"));

         pre_master = ka->derive_key(0, key_material).bits_of();
      }
      catch(...)
         {
         pre_master.resize(dh_priv->public_value().size());
         rng.randomize(pre_master, pre_master.size());
         }

      return pre_master;
      }
   else if(const RSA_PrivateKey* rsa_priv = dynamic_cast<const RSA_PrivateKey*>(priv_key))
      {
      std::auto_ptr<PK_Decryptor> decryptor(get_pk_decryptor(*rsa_priv,
                                                             "PKCS1v15"));

      try {
         pre_master = decryptor->decrypt(key_material);

         if(pre_master.size() != 48 ||
            make_u16bit(pre_master[0], pre_master[1]) != version)
            throw Decoding_Error("Client_Key_Exchange: Secret corrupted");
      }
      catch(std::exception)
         {
         pre_master.resize(48);
         rng.randomize(pre_master, pre_master.size());
         pre_master[0] = (version >> 8) & 0xFF;
         pre_master[1] = (version     ) & 0xFF;
         }

      return pre_master;
      }
   else
      throw Invalid_Argument("Client_Key_Exchange: Bad key for decrypt");
   }

/**
* Return the pre_master_secret
*/
SecureVector<byte> Client_Key_Exchange::pre_master_secret() const
   {
   return pre_master;
   }

}
<|endoftext|>


<commit_before>/*
 starfield.cpp
 Classic Invaders

 Copyright (c) 2013, Todd Steinackle, Simon Que
 All rights reserved.

 Redistribution and use in source and binary forms, with or without modification, are permitted
 provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice, this list of conditions
 and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright
 notice, this list of conditions and the following disclaimer in the documentation and/or other
 materials provided with the distribution.

 * Neither the name of The No Quarter Arcade (http://www.noquarterarcade.com/)  nor the names of
 its contributors may be used to endorse or promote products derived from this software without
 specific prior written permission.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
 IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/

#include "starfield.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef __AVR__
#include "cc_core.h"
#include "cc_tile_layer.h"
#endif

#include "screen.h"

#define MAX_LINE_SIZE     64
#define TILEMAP_WIDTH     32
#define TILEMAP_HEIGHT    32

// Generates randomized starfield tiles and tilemap.
void generate_starfield(Graphics::Screen* screen,
                        uint8_t layer, uint8_t palette,
                        uint8_t tile_width, uint8_t tile_height,
                        uint8_t num_tiles, uint16_t num_stars,
                        uint8_t min_brightness, uint8_t max_brightness) {
    if (tile_width > MAX_LINE_SIZE) {
        fprintf(stderr, "Starfield tiles cannot be wider than %u pixels.\n",
                MAX_LINE_SIZE);
        return;
    }
    if (max_brightness < min_brightness) {
        fprintf(stderr, " Min brightness must be lower than max brightness.\n");
        return;
    }

#ifdef __AVR__
    // Allocate space in VRAM.
    uint16_t vram_base;
    uint16_t tile_size = tile_width * tile_height;
    if (!screen->allocate_vram(tile_size * num_tiles, &vram_base)) {
        fprintf(stderr, "Could not allocate %u bytes in VRAM\n",
                tile_size * num_tiles);
        return;
    }

    // Generate the tiles.
    uint16_t offset = 0;
    for (uint8_t i = 0; i < num_tiles; ++i) {
        uint8_t buffer[MAX_LINE_SIZE];
        for (uint8_t y = 0; y < tile_height; ++y, offset += tile_width) {
            memset(buffer, 0, tile_width);
            for (uint8_t x = 0; x < tile_width; ++x) {
                uint16_t rand_num = rand() % (tile_width * tile_height);
                if (rand_num >= num_stars) {
                    continue;
                }
                uint8_t brightness = min_brightness +
                        (uint8_t)rand() % (max_brightness - min_brightness + 1);
                buffer[x] = brightness;
            }
            CC_SetVRAMData(buffer, vram_base + offset, tile_width);
        }
    }

    for (uint8_t y = 0; y < TILEMAP_HEIGHT; ++y) {
        uint16_t buffer[TILEMAP_WIDTH];
        for (uint8_t x = 0; x < TILEMAP_WIDTH; ++x)
            buffer[x] = rand() % num_tiles;
        screen->set_tilemap_data(layer, 0, y, buffer, sizeof(buffer));
    }

    // Set up grayscale palette.
    for (uint8_t color = 0; true ; ++color) {
        screen->set_palette_entry(palette, color, color, color, color);
        if (color == 0xff)
            break;
    }

    // Set up and enable the tile layer and tile map.
    screen->setup_tile_layer(layer, true, palette, vram_base, 0);
#endif  // defined (__AVR__)
}
<commit_msg>Convert starfield to Arduino<commit_after>/*
 starfield.cpp
 Classic Invaders

 Copyright (c) 2013, Todd Steinackle, Simon Que
 All rights reserved.

 Redistribution and use in source and binary forms, with or without modification, are permitted
 provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice, this list of conditions
 and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright
 notice, this list of conditions and the following disclaimer in the documentation and/or other
 materials provided with the distribution.

 * Neither the name of The No Quarter Arcade (http://www.noquarterarcade.com/)  nor the names of
 its contributors may be used to endorse or promote products derived from this software without
 specific prior written permission.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
 IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/

#include "starfield.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <DuinoCube.h>

#include "screen.h"

#define MAX_LINE_SIZE     64
#define TILEMAP_WIDTH     32
#define TILEMAP_HEIGHT    32

// Generates randomized starfield tiles and tilemap.
void generate_starfield(Graphics::Screen* screen,
                        uint8_t layer, uint8_t palette,
                        uint8_t tile_width, uint8_t tile_height,
                        uint8_t num_tiles, uint16_t num_stars,
                        uint8_t min_brightness, uint8_t max_brightness) {
    if (tile_width > MAX_LINE_SIZE) {
        fprintf(stderr, "Starfield tiles cannot be wider than %u pixels.\n",
                MAX_LINE_SIZE);
        return;
    }
    if (max_brightness < min_brightness) {
        fprintf(stderr, " Min brightness must be lower than max brightness.\n");
        return;
    }

    // Allocate space in VRAM.
    uint16_t vram_base;
    uint16_t tile_size = tile_width * tile_height;
    if (!screen->allocate_vram(tile_size * num_tiles, &vram_base)) {
        fprintf(stderr, "Could not allocate %u bytes in VRAM\n",
                tile_size * num_tiles);
        return;
    }
    DC.Core.writeWord(REG_SYS_CTRL, (1 << REG_SYS_CTRL_VRAM_ACCESS));
    DC.Core.writeWord(REG_MEM_BANK,
                      VRAM_BANK_BEGIN + vram_base / VRAM_BANK_SIZE);

    // Generate the tiles.
    uint16_t offset = 0;
    for (uint8_t i = 0; i < num_tiles; ++i) {
        uint8_t buffer[MAX_LINE_SIZE];
        for (uint8_t y = 0; y < tile_height; ++y, offset += tile_width) {
            memset(buffer, 0, tile_width);
            for (uint8_t x = 0; x < tile_width; ++x) {
                uint16_t rand_num = rand() % (tile_width * tile_height);
                if (rand_num >= num_stars) {
                    continue;
                }
                uint8_t brightness = min_brightness +
                        (uint8_t)rand() % (max_brightness - min_brightness + 1);
                buffer[x] = brightness;
            }
            printf("Writing %d bytes of starfield data to 0x%04x\n",
                   vram_base + offset);
            DC.Core.writeData(vram_base + offset, buffer, tile_width);
        }
    }
    DC.Core.writeWord(REG_SYS_CTRL, (0 << REG_SYS_CTRL_VRAM_ACCESS));

    DC.Core.writeWord(REG_MEM_BANK, TILEMAP_BANK);

    for (uint8_t y = 0; y < TILEMAP_HEIGHT; ++y) {
        uint16_t buffer[TILEMAP_WIDTH];
        for (uint8_t x = 0; x < TILEMAP_WIDTH; ++x)
            buffer[x] = rand() % num_tiles;
        screen->set_tilemap_data(layer, 0, y, buffer, sizeof(buffer));
    }

    // Set up grayscale palette.
    for (uint8_t color = 0; true ; ++color) {
        screen->set_palette_entry(palette, color, color, color, color);
        if (color == 0xff)
            break;
    }

    // Set up and enable the tile layer and tile map.
    screen->setup_tile_layer(layer, true, palette, vram_base, 0);
}
<|endoftext|>