<commit_before>#ifndef DICE_PARSER_HPP_
#define DICE_PARSER_HPP_

#include <memory>
#include <string>
#include <vector>
#include <ostream>
#include <functional>
#include <unordered_map>

#include "logger.hpp"
#include "value.hpp"
#include "lexer.hpp"
#include "symbols.hpp"
#include "environment.hpp"
#include "random_variable.hpp"

namespace dice
{
    // dice expression parser
    template<typename Lexer, typename Logger, typename Environment>
    class parser
    {
    public:
        using value_type = std::unique_ptr<base_value>;

        parser(Lexer* reader, Logger* log, Environment* env) :
            lexer_(reader),
            log_(log),
            env_(env) {}

        /** Parse expression provided by the lexer.
         * Operators are left associative unless stated otherwise.
         * List of operators (from lowest to highest precedence):
         * -#  = (assignment, non-associative)
         * -#  <, <=, !=, ==, >=, >, in (relational operators, non-assosiative)
         * -#  + (add), - (subtract)
         * -#  * (multiply), / (divide)
         * -#  - (unary minus)
         * -#  D|d (roll dice)
         * @return vector of computed values
         */
        std::vector<value_type> parse()
        {
            lookahead_ = lexer_->read_token();
            auto result = stmts();
            // make sure we've processed the whole expression
            eat(symbol_type::end);
            return result;
        }

    private:
        Lexer* lexer_;
        Logger* log_;
        Environment* env_;
        symbol lookahead_;

        std::vector<value_type> stmts()
        {
            while (lookahead_.type != symbol_type::end && !in_first_stmt())
            {
                error("Invalid token at the beginning of an expression: " +
                    to_string(lookahead_));
                eat(lookahead_.type);
            }

            std::vector<value_type> values;
            if (lookahead_.type == symbol_type::end)
            {
                return values;
            }

            values.push_back(stmt());
            for (;;)
            {
                if (lookahead_.type == symbol_type::semicolon)
                {
                    eat(lookahead_.type);
                    if (check_stmt())
                    {
                        values.push_back(stmt());
                    }
                    else
                    {
                        error("Invalid statement.");
                    }
                }
                else
                {
                    break;
                }
            }
            return values;
        }

        bool in_first_stmt() const
        {
            return lookahead_.type == symbol_type::var ||
                in_first_expr();
        }

        bool in_follow_stmt() const
        {
            return lookahead_.type == symbol_type::semicolon ||
                // FOLLOW(stmts):
                lookahead_.type == symbol_type::end;
        }

        bool check_stmt()
        {
            while (!in_follow_stmt() && !in_first_stmt())
            {
                error("Invalid token at the beginning of a statement: " +
                    to_string(lookahead_));
                eat(lookahead_.type);
            }
            return in_first_stmt();
        }

        value_type stmt()
        {
            if (lookahead_.type == symbol_type::var)
            {
                eat(lookahead_.type);
                auto id = lookahead_;
                eat(symbol_type::id);
                eat(symbol_type::assign);
                auto value = expr();

                env_->set_var(id.lexeme, std::move(value));
                return nullptr;
            }
            return expr();
        }

        bool check_expr()
        {
            while (!in_follow_expr() && !in_first_expr())
            {
                error("Invalid token at the beginning of an expression: " +
                    to_string(lookahead_));
                eat(lookahead_.type);
            }
            return in_first_expr();
        }

        // true <=> next token is in FIRST(expr)
        bool in_first_expr() const
        {
            return in_first_add();
        }

        // true <=> next token is in FOLLOW(expr)
        bool in_follow_expr() const
        {
            return lookahead_.type == symbol_type::end ||
                lookahead_.type == symbol_type::right_paren ||
                in_follow_param_list();
        }

        value_type expr()
        {
            auto left = add();
            if (lookahead_.type == symbol_type::in)
            {
                eat(symbol_type::in);
                eat(symbol_type::left_square_bracket);

                // parse lower bound of the interval
                if (!check_add())
                {
                    error(
                        "Invalid operand for the lower bound of operator in");
                    return left;
                }
                auto lower_bound = add();

                eat(symbol_type::param_delim);

                // parse upper bound of the interval
                if (!check_add())
                {
                    error(
                        "Invalid operand for the upper bound of operator in");
                    return left;
                }
                auto upper_bound = add();

                eat(symbol_type::right_square_bracket);

                return env_->call("in",
                    std::move(left),
                    std::move(lower_bound),
                    std::move(upper_bound));
            }
            else if (lookahead_.type == symbol_type::rel_op)
            {
                auto op = lookahead_;
                eat(symbol_type::rel_op);
                if (check_add())
                {
                    auto right = add();
                    return env_->call(op.lexeme, std::move(left),
                        std::move(right));
                }
                else
                {
                    error("Invalid operand for " + to_string(op));
                }
            }
            return left;
        }

        // true <=> next token is in FIRST(add)
        bool in_first_add() const
        {
            return in_first_mult();
        }

        // true <=> next token is in FOLLOW(add)
        bool in_follow_add() const
        {
            return lookahead_.type == symbol_type::plus ||
                lookahead_.type == symbol_type::minus ||
                lookahead_.type == symbol_type::in ||
                lookahead_.type == symbol_type::rel_op ||
                lookahead_.type == symbol_type::param_delim ||
                lookahead_.type == symbol_type::right_square_bracket ||
                in_follow_expr();
        }

        bool check_add()
        {
            while (!in_first_add() && !in_follow_add())
            {
                error("Invalid token at the beginning of an addition: " +
                    to_string(lookahead_));
                eat(lookahead_.type);
            }
            return in_first_add();
        }

        value_type add()
        {
            std::string op;
            auto result = mult();
            for (;;)
            {
                // decide on the next operation
                if (lookahead_.type == symbol_type::plus)
                {
                    eat(symbol_type::plus);
                    op = "+";
                }
                else if (lookahead_.type == symbol_type::minus)
                {
                    eat(symbol_type::minus);
                    op = "-";
                }
                else
                {
                    break;
                }

                // compute the operator if there won't be any parse error
                if (check_mult())
                {
                    result = env_->call(op, std::move(result), mult());
                }
                else // otherwise, ignore the operator
                {
                    error("Invalid operand for binary operator " + op);
                }
            }
            return result;
        }

        // true <=> next token is in FIRST(mult)
        bool in_first_mult() const
        {
            return in_first_dice_roll();
        }

        // true <=> next token is in FOLLOW(mult)
        bool in_follow_mult() const
        {
            return lookahead_.type == symbol_type::times ||
                lookahead_.type == symbol_type::divide ||
                in_follow_add();
        }

        bool check_mult()
        {
            while (!in_first_mult() && !in_follow_mult())
            {
                error("Invalid token at the beginning of a multiplication: " +
                    to_string(lookahead_));
                eat(lookahead_.type);
            }
            return in_first_mult();
        }

        value_type mult()
        {
            std::string op;
            auto result = dice_roll();
            for (;;)
            {
                // decide on the next operation
                if (lookahead_.type == symbol_type::times)
                {
                    eat(symbol_type::times);
                    op = "*";
                }
                else if (lookahead_.type == symbol_type::divide)
                {
                    eat(symbol_type::divide);
                    op = "/";
                }
                else
                {
                    break;
                }

                // compute the operation if there won't be any parse error
                if (check_dice_roll())
                {
                    result = env_->call(op, std::move(result), dice_roll());
                }
                else // otherwise, ignore the operator
                {
                    error("Invalid operand for binary operator " + op);
                }
            }
            return result;
        }

        // true <=> next token is in FIRST(dice_roll)
        bool in_first_dice_roll() const
        {
            return lookahead_.type == symbol_type::minus ||
                in_first_factor();
        }

        // true <=> next token is in FOLLOW(dice_roll)
        bool in_follow_dice_roll() const
        {
            return lookahead_.type == symbol_type::roll_op ||
               in_follow_mult();
        }

        bool check_dice_roll()
        {
            while (!in_first_dice_roll() && !in_follow_dice_roll())
            {
                error("Invalid token at the beginning of a dice roll: " +
                    to_string(lookahead_));
                eat(lookahead_.type);
            }
            return in_first_dice_roll();
        }

        value_type dice_roll()
        {
            // determine the sign
            int count = 0;
            for (;;)
            {
                if (lookahead_.type == symbol_type::minus)
                {
                    eat(symbol_type::minus);
                    ++count;
                }
                else
                {
                    break;
                }
            }

            // parse dice roll
            auto result = factor();
            for (;;)
            {
                if (lookahead_.type == symbol_type::roll_op)
                {
                    eat(symbol_type::roll_op);

                    // only use the factor production if there won't be any
                    // parse error
                    if (check_factor())
                    {
                        result = env_->call("__roll_op", std::move(result),
                            factor());
                    }
                    else // otherwise, ignore the operator
                    {
                        error("Invalid operand for binary operator "
                            "D (dice roll)");
                    }
                }
                else
                {
                    break;
                }
            }

            // add sign
            if (count % 2 != 0)
                result = env_->call("unary-", std::move(result));
            return result;
        }

        // true <=> next token is in FIRST(factor)
        bool in_first_factor() const
        {
            return lookahead_.type == symbol_type::left_paren ||
                lookahead_.type == symbol_type::number ||
                lookahead_.type == symbol_type::id;
        }

        // true <=> next token is in FOLLOW(factor)
        bool in_follow_factor() const
        {
            return in_follow_dice_roll();
        }

        bool check_factor()
        {
            while (!in_first_factor() && !in_follow_factor())
            {
                error("Invalid token at the beginning of a factor: " +
                    to_string(lookahead_));
                eat(lookahead_.type);
            }
            return in_first_factor();
        }

        value_type factor()
        {
            if (lookahead_.type == symbol_type::left_paren)
            {
                eat(symbol_type::left_paren);
                auto result = expr();
                eat(symbol_type::right_paren);
                return result;
            }
            else if (lookahead_.type == symbol_type::number)
            {
                auto lexeme = lookahead_.lexeme;
                eat(lookahead_.type);
                if (lexeme.find('.') != std::string::npos)
                {
                    return make<type_double>(std::atof(lexeme.c_str()));
                }
                else
                {
                    return make<type_int>(std::atoi(lexeme.c_str()));
                }
            }
            else if (lookahead_.type == symbol_type::id)
            {
                auto id = lookahead_;
                eat(symbol_type::id);

                if (lookahead_.type == symbol_type::left_paren)
                {
                    // function call
                    eat(symbol_type::left_paren);
                    auto args = param_list();
                    eat(symbol_type::right_paren);

                    return env_->call_var(id.lexeme, args.begin(), args.end());
                }
                else // variable
                {
                    auto value = env_->get_var(id.lexeme);
                    if (value == nullptr)
                    {
                        error("Unknown variable '" + id.lexeme + "'.");
                        return make<type_int>(0);
                    }

                    // if the name represents a random variable, it can
                    // depend on other subexpressions
                    auto var = dynamic_cast<type_rand_var*>(value);
                    if (var != nullptr)
                    {
                        return make<type_rand_var>(
                            dependent_tag{},
                            &var->data().rand_var()
                        );
                    }

                    return value->clone();
                }
            }

            error("Expected " + to_string(symbol_type::left_paren) + ", " +
                to_string(symbol_type::number) + " or " +
                to_string(symbol_type::id) +  ", got " +
                to_string(lookahead_) + ".");
            return make<type_int>(0);
        }

        // true <=> next token is in FIRST(param_list)
        bool in_first_param_list() const
        {
            return lookahead_.type == symbol_type::right_paren ||
                in_first_expr();
        }

        // true <=> next token is in FOLLOW(param_list)
        bool in_follow_param_list() const
        {
            return lookahead_.type == symbol_type::param_delim ||
                // FOLLOW(opt_params):
                lookahead_.type == symbol_type::right_paren;
        }

        bool check_param_list()
        {
            while (!in_first_param_list() && !in_follow_param_list())
            {
                error("Invalid token at the beginning of parameter list: " +
                    to_string(lookahead_));
                eat(lookahead_.type);
            }
            return in_first_param_list();
        }

        std::vector<value_type> param_list()
        {
            std::vector<value_type> args;
            if (lookahead_.type == symbol_type::right_paren)
            {
                return args; // no arguments
            }

            std::size_t number = 0;
            for (;;)
            {
                if (check_expr())
                {
                    args.emplace_back(expr());
                }
                else
                {
                    error("Invalid function parameter " +
                        std::to_string(number));
                }

                if (lookahead_.type != symbol_type::param_delim)
                {
                    break;
                }
                eat(symbol_type::param_delim);
                ++number;
            }
            return args;
        }

        /** Read token of given type from the input.
         * If there is no such token, "add" it at current position.
         * New token is read into the lookahead_ variable.
         * @param expected type
         */
        void eat(symbol_type type)
        {
            if (lookahead_.type != type)
            {
                // report the error and "insert" the token
                // (i.e. assume it's there)
                error("Expected " +
                    to_string(type) + ", got " +
                    to_string(lookahead_) + ".");
            }
            lookahead_ = lexer_->read_token();
        }

        /** Report a parsing error.
         * @param error message
         */
        void error(const std::string& message)
        {
            log_->error(
                lexer_->location().line,
                lexer_->location().col,
                message);
        }
    };
}

#endif // DICE_PARSER_HPP_<commit_msg>Add warning about using names of rand vars<commit_after>#ifndef DICE_PARSER_HPP_
#define DICE_PARSER_HPP_

#include <memory>
#include <string>
#include <vector>
#include <ostream>
#include <functional>
#include <unordered_map>

#include "logger.hpp"
#include "value.hpp"
#include "lexer.hpp"
#include "symbols.hpp"
#include "environment.hpp"
#include "random_variable.hpp"

namespace dice
{
    // dice expression parser
    template<typename Lexer, typename Logger, typename Environment>
    class parser
    {
    public:
        using value_type = std::unique_ptr<base_value>;

        parser(Lexer* reader, Logger* log, Environment* env) :
            lexer_(reader),
            log_(log),
            env_(env) {}

        /** Parse expression provided by the lexer.
         * Operators are left associative unless stated otherwise.
         * List of operators (from lowest to highest precedence):
         * -#  = (assignment, non-associative)
         * -#  <, <=, !=, ==, >=, >, in (relational operators, non-assosiative)
         * -#  + (add), - (subtract)
         * -#  * (multiply), / (divide)
         * -#  - (unary minus)
         * -#  D|d (roll dice)
         * @return vector of computed values
         */
        std::vector<value_type> parse()
        {
            lookahead_ = lexer_->read_token();
            auto result = stmts();
            // make sure we've processed the whole expression
            eat(symbol_type::end);
            return result;
        }

    private:
        Lexer* lexer_;
        Logger* log_;
        Environment* env_;
        symbol lookahead_;
        bool is_definition_ = false;

        std::vector<value_type> stmts()
        {
            while (lookahead_.type != symbol_type::end && !in_first_stmt())
            {
                error("Invalid token at the beginning of an expression: " +
                    to_string(lookahead_));
                eat(lookahead_.type);
            }

            std::vector<value_type> values;
            if (lookahead_.type == symbol_type::end)
            {
                return values;
            }

            values.push_back(stmt());
            for (;;)
            {
                if (lookahead_.type == symbol_type::semicolon)
                {
                    eat(lookahead_.type);
                    if (check_stmt())
                    {
                        values.push_back(stmt());
                    }
                    else
                    {
                        error("Invalid statement.");
                    }
                }
                else
                {
                    break;
                }
            }
            return values;
        }

        bool in_first_stmt() const
        {
            return lookahead_.type == symbol_type::var ||
                in_first_expr();
        }

        bool in_follow_stmt() const
        {
            return lookahead_.type == symbol_type::semicolon ||
                // FOLLOW(stmts):
                lookahead_.type == symbol_type::end;
        }

        bool check_stmt()
        {
            while (!in_follow_stmt() && !in_first_stmt())
            {
                error("Invalid token at the beginning of a statement: " +
                    to_string(lookahead_));
                eat(lookahead_.type);
            }
            return in_first_stmt();
        }

        value_type stmt()
        {
            if (lookahead_.type == symbol_type::var)
            {
                eat(lookahead_.type);
                auto id = lookahead_;
                eat(symbol_type::id);
                eat(symbol_type::assign);

                is_definition_ = true;
                auto value = expr();
                is_definition_ = false;

                env_->set_var(id.lexeme, std::move(value));
                return nullptr;
            }
            return expr();
        }

        bool check_expr()
        {
            while (!in_follow_expr() && !in_first_expr())
            {
                error("Invalid token at the beginning of an expression: " +
                    to_string(lookahead_));
                eat(lookahead_.type);
            }
            return in_first_expr();
        }

        // true <=> next token is in FIRST(expr)
        bool in_first_expr() const
        {
            return in_first_add();
        }

        // true <=> next token is in FOLLOW(expr)
        bool in_follow_expr() const
        {
            return lookahead_.type == symbol_type::end ||
                lookahead_.type == symbol_type::right_paren ||
                in_follow_param_list();
        }

        value_type expr()
        {
            auto left = add();
            if (lookahead_.type == symbol_type::in)
            {
                eat(symbol_type::in);
                eat(symbol_type::left_square_bracket);

                // parse lower bound of the interval
                if (!check_add())
                {
                    error(
                        "Invalid operand for the lower bound of operator in");
                    return left;
                }
                auto lower_bound = add();

                eat(symbol_type::param_delim);

                // parse upper bound of the interval
                if (!check_add())
                {
                    error(
                        "Invalid operand for the upper bound of operator in");
                    return left;
                }
                auto upper_bound = add();

                eat(symbol_type::right_square_bracket);

                return env_->call("in",
                    std::move(left),
                    std::move(lower_bound),
                    std::move(upper_bound));
            }
            else if (lookahead_.type == symbol_type::rel_op)
            {
                auto op = lookahead_;
                eat(symbol_type::rel_op);
                if (check_add())
                {
                    auto right = add();
                    return env_->call(op.lexeme, std::move(left),
                        std::move(right));
                }
                else
                {
                    error("Invalid operand for " + to_string(op));
                }
            }
            return left;
        }

        // true <=> next token is in FIRST(add)
        bool in_first_add() const
        {
            return in_first_mult();
        }

        // true <=> next token is in FOLLOW(add)
        bool in_follow_add() const
        {
            return lookahead_.type == symbol_type::plus ||
                lookahead_.type == symbol_type::minus ||
                lookahead_.type == symbol_type::in ||
                lookahead_.type == symbol_type::rel_op ||
                lookahead_.type == symbol_type::param_delim ||
                lookahead_.type == symbol_type::right_square_bracket ||
                in_follow_expr();
        }

        bool check_add()
        {
            while (!in_first_add() && !in_follow_add())
            {
                error("Invalid token at the beginning of an addition: " +
                    to_string(lookahead_));
                eat(lookahead_.type);
            }
            return in_first_add();
        }

        value_type add()
        {
            std::string op;
            auto result = mult();
            for (;;)
            {
                // decide on the next operation
                if (lookahead_.type == symbol_type::plus)
                {
                    eat(symbol_type::plus);
                    op = "+";
                }
                else if (lookahead_.type == symbol_type::minus)
                {
                    eat(symbol_type::minus);
                    op = "-";
                }
                else
                {
                    break;
                }

                // compute the operator if there won't be any parse error
                if (check_mult())
                {
                    result = env_->call(op, std::move(result), mult());
                }
                else // otherwise, ignore the operator
                {
                    error("Invalid operand for binary operator " + op);
                }
            }
            return result;
        }

        // true <=> next token is in FIRST(mult)
        bool in_first_mult() const
        {
            return in_first_dice_roll();
        }

        // true <=> next token is in FOLLOW(mult)
        bool in_follow_mult() const
        {
            return lookahead_.type == symbol_type::times ||
                lookahead_.type == symbol_type::divide ||
                in_follow_add();
        }

        bool check_mult()
        {
            while (!in_first_mult() && !in_follow_mult())
            {
                error("Invalid token at the beginning of a multiplication: " +
                    to_string(lookahead_));
                eat(lookahead_.type);
            }
            return in_first_mult();
        }

        value_type mult()
        {
            std::string op;
            auto result = dice_roll();
            for (;;)
            {
                // decide on the next operation
                if (lookahead_.type == symbol_type::times)
                {
                    eat(symbol_type::times);
                    op = "*";
                }
                else if (lookahead_.type == symbol_type::divide)
                {
                    eat(symbol_type::divide);
                    op = "/";
                }
                else
                {
                    break;
                }

                // compute the operation if there won't be any parse error
                if (check_dice_roll())
                {
                    result = env_->call(op, std::move(result), dice_roll());
                }
                else // otherwise, ignore the operator
                {
                    error("Invalid operand for binary operator " + op);
                }
            }
            return result;
        }

        // true <=> next token is in FIRST(dice_roll)
        bool in_first_dice_roll() const
        {
            return lookahead_.type == symbol_type::minus ||
                in_first_factor();
        }

        // true <=> next token is in FOLLOW(dice_roll)
        bool in_follow_dice_roll() const
        {
            return lookahead_.type == symbol_type::roll_op ||
               in_follow_mult();
        }

        bool check_dice_roll()
        {
            while (!in_first_dice_roll() && !in_follow_dice_roll())
            {
                error("Invalid token at the beginning of a dice roll: " +
                    to_string(lookahead_));
                eat(lookahead_.type);
            }
            return in_first_dice_roll();
        }

        value_type dice_roll()
        {
            // determine the sign
            int count = 0;
            for (;;)
            {
                if (lookahead_.type == symbol_type::minus)
                {
                    eat(symbol_type::minus);
                    ++count;
                }
                else
                {
                    break;
                }
            }

            // parse dice roll
            auto result = factor();
            for (;;)
            {
                if (lookahead_.type == symbol_type::roll_op)
                {
                    eat(symbol_type::roll_op);

                    // only use the factor production if there won't be any
                    // parse error
                    if (check_factor())
                    {
                        result = env_->call("__roll_op", std::move(result),
                            factor());
                    }
                    else // otherwise, ignore the operator
                    {
                        error("Invalid operand for binary operator "
                            "D (dice roll)");
                    }
                }
                else
                {
                    break;
                }
            }

            // add sign
            if (count % 2 != 0)
                result = env_->call("unary-", std::move(result));
            return result;
        }

        // true <=> next token is in FIRST(factor)
        bool in_first_factor() const
        {
            return lookahead_.type == symbol_type::left_paren ||
                lookahead_.type == symbol_type::number ||
                lookahead_.type == symbol_type::id;
        }

        // true <=> next token is in FOLLOW(factor)
        bool in_follow_factor() const
        {
            return in_follow_dice_roll();
        }

        bool check_factor()
        {
            while (!in_first_factor() && !in_follow_factor())
            {
                error("Invalid token at the beginning of a factor: " +
                    to_string(lookahead_));
                eat(lookahead_.type);
            }
            return in_first_factor();
        }

        value_type factor()
        {
            if (lookahead_.type == symbol_type::left_paren)
            {
                eat(symbol_type::left_paren);
                auto result = expr();
                eat(symbol_type::right_paren);
                return result;
            }
            else if (lookahead_.type == symbol_type::number)
            {
                auto lexeme = lookahead_.lexeme;
                eat(lookahead_.type);
                if (lexeme.find('.') != std::string::npos)
                {
                    return make<type_double>(std::atof(lexeme.c_str()));
                }
                else
                {
                    return make<type_int>(std::atoi(lexeme.c_str()));
                }
            }
            else if (lookahead_.type == symbol_type::id)
            {
                auto id = lookahead_;
                eat(symbol_type::id);

                if (lookahead_.type == symbol_type::left_paren)
                {
                    // function call
                    eat(symbol_type::left_paren);
                    auto args = param_list();
                    eat(symbol_type::right_paren);

                    return env_->call_var(id.lexeme, args.begin(), args.end());
                }
                else // variable
                {
                    auto value = env_->get_var(id.lexeme);
                    if (value == nullptr)
                    {
                        error("Unknown variable '" + id.lexeme + "'.");
                        return make<type_int>(0);
                    }

                    // if the name represents a random variable, it can
                    // depend on other subexpressions
                    auto var = dynamic_cast<type_rand_var*>(value);
                    if (var != nullptr)
                    {
                        if (is_definition_)
                        {
                            error("Using names of random variables in name "
                                "definition is supported only partially and "
                                "may lead to incorrect results.");
                        }

                        return make<type_rand_var>(
                            dependent_tag{},
                            &var->data().rand_var()
                        );
                    }

                    return value->clone();
                }
            }

            error("Expected " + to_string(symbol_type::left_paren) + ", " +
                to_string(symbol_type::number) + " or " +
                to_string(symbol_type::id) +  ", got " +
                to_string(lookahead_) + ".");
            return make<type_int>(0);
        }

        // true <=> next token is in FIRST(param_list)
        bool in_first_param_list() const
        {
            return lookahead_.type == symbol_type::right_paren ||
                in_first_expr();
        }

        // true <=> next token is in FOLLOW(param_list)
        bool in_follow_param_list() const
        {
            return lookahead_.type == symbol_type::param_delim ||
                // FOLLOW(opt_params):
                lookahead_.type == symbol_type::right_paren;
        }

        bool check_param_list()
        {
            while (!in_first_param_list() && !in_follow_param_list())
            {
                error("Invalid token at the beginning of parameter list: " +
                    to_string(lookahead_));
                eat(lookahead_.type);
            }
            return in_first_param_list();
        }

        std::vector<value_type> param_list()
        {
            std::vector<value_type> args;
            if (lookahead_.type == symbol_type::right_paren)
            {
                return args; // no arguments
            }

            std::size_t number = 0;
            for (;;)
            {
                if (check_expr())
                {
                    args.emplace_back(expr());
                }
                else
                {
                    error("Invalid function parameter " +
                        std::to_string(number));
                }

                if (lookahead_.type != symbol_type::param_delim)
                {
                    break;
                }
                eat(symbol_type::param_delim);
                ++number;
            }
            return args;
        }

        /** Read token of given type from the input.
         * If there is no such token, "add" it at current position.
         * New token is read into the lookahead_ variable.
         * @param expected type
         */
        void eat(symbol_type type)
        {
            if (lookahead_.type != type)
            {
                // report the error and "insert" the token
                // (i.e. assume it's there)
                error("Expected " +
                    to_string(type) + ", got " +
                    to_string(lookahead_) + ".");
            }
            lookahead_ = lexer_->read_token();
        }

        /** Report a parsing error.
         * @param error message
         */
        void error(const std::string& message)
        {
            log_->error(
                lexer_->location().line,
                lexer_->location().col,
                message);
        }
    };
}

#endif // DICE_PARSER_HPP_<|endoftext|>


<commit_before>#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>

#define MAX_BUF 1024

#include <sstream>
#include <iostream>
#include <string>
using namespace std;
#include <boost/property_tree/json_parser.hpp>

static int fd = -1;
#include <signal.h>
#include <stdio.h>
void sigcatch(int) {
	if(fd > 0) {
		close(fd);
	}
	exit(0);
}
int main(int ac,char*av[])
{
	system("rm -f /tmp/mpu.6050.unix.domain");
	if (SIG_ERR == signal(SIGINT, sigcatch)) {
		printf("failed to set signal handler.n");
		exit(1);
	}
     fd = socket( AF_LOCAL, SOCK_DGRAM, 0 );

	struct sockaddr_un addr;
	bzero( &addr, sizeof(addr) );
	addr.sun_family = AF_LOCAL;
	strcpy( addr.sun_path, "/tmp/mpu.6050.unix.domain" );

   int use = 1;
   if (::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &use, sizeof(int)) < 0) {
    perror("setsockopt(SO_REUSEADDR) failed");
   }
   if(::bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0)
   {

     printf(" cannot bind socket: %d. \n",errno);
     close(fd);

     return 0;

   }

    char buf[MAX_BUF];
    double degree = 20.0;
    double startDeg = 0.0;
    bool first = true;
    while(degree >0) {
    	socklen_t len = sizeof(addr);
        int ret = ::recvfrom(fd, buf, MAX_BUF, 0, (struct sockaddr *)&addr, &len);
        if(ret>0){
            //printf("Received: %s\n", buf);
            string recvStr(buf,ret);
            //std::cout << recvStr << std::endl;
            std::stringstream ss;
            ss << recvStr;
            try {
            	boost::property_tree::ptree pt;
            	boost::property_tree::read_json(ss, pt);
            	auto current = pt.get<double>("yaw");
            	//std::cout <<  current << std::endl;
            	if(first) {
            		startDeg = current;
            		first = false;
            	}
            	auto diff = current - startDeg;
            	std::cout <<  "diff=<" << diff <<">"<< std::endl;
            	if( diff >= degree) {
            		break;
            	}
            } catch(std::exception e) {
            	std::cout << e.what() << std::endl;
            }
        } else if (ret==0){
        } else {
            printf("ret=<%d>\n",ret);
        }
    }
    close(fd);

    return 0;
}
<commit_msg>Update turn.cpp<commit_after>#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>

#define MAX_BUF 1024

#include <sstream>
#include <iostream>
#include <string>
using namespace std;
#include <boost/property_tree/json_parser.hpp>

static int fd = -1;
#include <signal.h>
#include <stdio.h>
void sigcatch(int) {
	if(fd > 0) {
		close(fd);
	}
	exit(0);
}
int main(int ac,char*av[])
{
	system("rm -f /tmp/mpu.6050.unix.domain");
	if (SIG_ERR == signal(SIGINT, sigcatch)) {
		printf("failed to set signal handler.n");
		exit(1);
	}
     fd = socket( AF_LOCAL, SOCK_DGRAM, 0 );

	struct sockaddr_un addr;
	bzero( &addr, sizeof(addr) );
	addr.sun_family = AF_LOCAL;
	strcpy( addr.sun_path, "/tmp/mpu.6050.unix.domain" );

   int use = 1;
   if (::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &use, sizeof(int)) < 0) {
    perror("setsockopt(SO_REUSEADDR) failed");
   }
   if(::bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0)
   {

     printf(" cannot bind socket: %d. \n",errno);
     close(fd);

     return 0;

   }

    char buf[MAX_BUF];
    double degree = 20.0;
    if(ac > 1) {
    	degree = ::atof(av[1]);
    }
    degree = std::fabs(degree);
    double startDeg = 0.0;
    bool first = true;
    while(degree >0) {
    	socklen_t len = sizeof(addr);
        int ret = ::recvfrom(fd, buf, MAX_BUF, 0, (struct sockaddr *)&addr, &len);
        if(ret>0){
            //printf("Received: %s\n", buf);
            string recvStr(buf,ret);
            //std::cout << recvStr << std::endl;
            std::stringstream ss;
            ss << recvStr;
            try {
            	boost::property_tree::ptree pt;
            	boost::property_tree::read_json(ss, pt);
            	auto current = pt.get<double>("yaw");
            	//std::cout <<  current << std::endl;
            	if(first) {
            		startDeg = current;
            		first = false;
            	}
            	auto diff = std::fabs(current - startDeg);
            	std::cout <<  "diff=<" << diff <<">"<< std::endl;
            	if( diff >= degree) {
            		break;
            	}
            } catch(std::exception e) {
            	std::cout << e.what() << std::endl;
            }
        } else if (ret==0){
        } else {
            printf("ret=<%d>\n",ret);
        }
    }
    close(fd);

    return 0;
}
<|endoftext|>


<commit_before>// Copyright (c) 2010 Satoshi Nakamoto
// Copyright (c) 2009-2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "assert.h"

#include "chainparams.h"
#include "core.h"
#include "protocol.h"
#include "util.h"

//
// Main network
//

unsigned int pnSeed[] =
{
    0x12345678
};

class CMainParams : public CChainParams {
public:
    CMainParams() {
        // The message start string is designed to be unlikely to occur in normal data.
        pchMessageStart[0] = 0x04;
        pchMessageStart[1] = 0x04;
        pchMessageStart[2] = 0x04;
        pchMessageStart[3] = 0x04;
        nDefaultPort = 5530;
        nRPCPort = 5531;
        bnProofOfWorkLimit = CBigNum(~uint256(0) >> 20);
        nSubsidyHalvingInterval = 100000;

        // Build the genesis block. Note that the output of the genesis coinbase cannot
        // be spent as it did not originally exist in the database.

        const char* pszTimestamp = "ABCCoin";
        CTransaction txNew;
        txNew.vin.resize(1);
        txNew.vout.resize(1);
        txNew.vin[0].scriptSig = CScript() << 486604799 << CBigNum(4) << vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));
        txNew.vout[0].nValue = 1 * COIN;
        txNew.vout[0].scriptPubKey = CScript() << ParseHex("") << OP_CHECKSIG;
        genesis.vtx.push_back(txNew);
        genesis.hashPrevBlock = 0;
        genesis.hashMerkleRoot = genesis.BuildMerkleTree();
        genesis.nVersion = 1;
        genesis.nTime    = 1300000000;
        genesis.nBits    = 0x1e0fffff;
        genesis.nNonce   = 0;

        //// debug print
        hashGenesisBlock = genesis.GetHash();
        //while (hashGenesisBlock > bnProofOfWorkLimit.getuint256()){
        //    if (++genesis.nNonce==0) break;
        //    hashGenesisBlock = genesis.GetHash();
        //}

        printf("%s\n", hashGenesisBlock.ToString().c_str());
        printf("%s\n", genesis.hashMerkleRoot.ToString().c_str());
        printf("%x\n", bnProofOfWorkLimit.GetCompact());
        genesis.print();

        assert(hashGenesisBlock == uint256("0x"));
        assert(genesis.hashMerkleRoot == uint256("0x"));

        vSeeds.push_back(CDNSSeedData("someaddress.com or IP addy", "someaddress.com"));

        base58Prefixes[PUBKEY_ADDRESS] = 36;
        base58Prefixes[SCRIPT_ADDRESS] = 30;
        base58Prefixes[SECRET_KEY] = 224;

        // Convert the pnSeeds array into usable address objects.
        for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++)
        {
            // It'll only connect to one or two seed nodes because once it connects,
            // it'll get a pile of addresses with newer timestamps.
            // Seed nodes are given a random 'last seen time'
            const int64 nTwoDays = 2 * 24 * 60 * 60;
            struct in_addr ip;
            memcpy(&ip, &pnSeed[i], sizeof(ip));
            CAddress addr(CService(ip, GetDefaultPort()));
            addr.nTime = GetTime() - GetRand(nTwoDays) - nTwoDays;
            vFixedSeeds.push_back(addr);
        }
    }

    virtual const CBlock& GenesisBlock() const { return genesis; }
    virtual Network NetworkID() const { return CChainParams::MAIN; }

    virtual const vector<CAddress>& FixedSeeds() const {
        return vFixedSeeds;
    }
protected:
    CBlock genesis;
    vector<CAddress> vFixedSeeds;
};
static CMainParams mainParams;

//
// Testnet (v3)
//
class CTestNetParams : public CMainParams {
public:
    CTestNetParams() {
        // The message start string is designed to be unlikely to occur in normal data.
        pchMessageStart[0] = 0x01;
        pchMessageStart[1] = 0xfe;
        pchMessageStart[2] = 0xfe;
        pchMessageStart[3] = 0x05;
        nDefaultPort = 55534;
        nRPCPort = 55535;
        strDataDir = "testnet";

        // Modify the testnet genesis block so the timestamp is valid for a later start.
        genesis.nTime = 1374901773;
        genesis.nNonce = 1211565;

        //// debug print
        hashGenesisBlock = genesis.GetHash();
        //while (hashGenesisBlock > bnProofOfWorkLimit.getuint256()){
        //    if (++genesis.nNonce==0) break;
        //   hashGenesisBlock = genesis.GetHash();
        //}

        printf("%s\n", hashGenesisBlock.ToString().c_str());
        printf("%s\n", genesis.hashMerkleRoot.ToString().c_str());
        genesis.print();

        vFixedSeeds.clear();
        vSeeds.clear();
        // vSeeds.push_back(CDNSSeedData("abccoin.test", "test.abccoin.org"));

        base58Prefixes[PUBKEY_ADDRESS] = 130;
        base58Prefixes[SCRIPT_ADDRESS] = 30;
        base58Prefixes[SECRET_KEY] = 239;

    }
    virtual Network NetworkID() const { return CChainParams::TESTNET; }
};
static CTestNetParams testNetParams;

//
// Regression test
//
class CRegTestParams : public CTestNetParams {
public:
    CRegTestParams() {
        pchMessageStart[0] = 0xfa;
        pchMessageStart[1] = 0x0f;
        pchMessageStart[2] = 0xa5;
        pchMessageStart[3] = 0x5a;
        nSubsidyHalvingInterval = 150;
        bnProofOfWorkLimit = CBigNum(~uint256(0) >> 1);
        genesis.nTime = 1296688602;
        genesis.nBits = 0x207fffff;
        genesis.nNonce = 3;
        hashGenesisBlock = genesis.GetHash();
        nDefaultPort = 18444;
        strDataDir = "regtest";

        //// debug print
        hashGenesisBlock = genesis.GetHash();
        //while (hashGenesisBlock > bnProofOfWorkLimit.getuint256()){
        //    if (++genesis.nNonce==0) break;
        //    hashGenesisBlock = genesis.GetHash();
        //}

        printf("%s\n", hashGenesisBlock.ToString().c_str());
        printf("%s\n", genesis.hashMerkleRoot.ToString().c_str());
        genesis.print();

        // assert(hashGenesisBlock == uint256("0x13d8d31dde96874006da503dd2b63fa68c698dc823334359e417aa3a92f80433"));

        vSeeds.clear();  // Regtest mode doesn't have any DNS seeds.

        base58Prefixes[PUBKEY_ADDRESS] = 0;
        base58Prefixes[SCRIPT_ADDRESS] = 5;
        base58Prefixes[SECRET_KEY] = 128;
    }

    virtual bool RequireRPCPassword() const { return false; }
    virtual Network NetworkID() const { return CChainParams::REGTEST; }
};
static CRegTestParams regTestParams;

static CChainParams *pCurrentParams = &mainParams;

const CChainParams &Params() {
    return *pCurrentParams;
}

void SelectParams(CChainParams::Network network) {
    switch (network) {
        case CChainParams::MAIN:
            pCurrentParams = &mainParams;
            break;
        case CChainParams::TESTNET:
            pCurrentParams = &testNetParams;
            break;
        case CChainParams::REGTEST:
            pCurrentParams = &regTestParams;
            break;
        default:
            assert(false && "Unimplemented network");
            return;
    }
}

bool SelectParamsFromCommandLine() {
    bool fRegTest = GetBoolArg("-regtest", false);
    bool fTestNet = GetBoolArg("-testnet", false);

    if (fTestNet && fRegTest) {
        return false;
    }

    if (fRegTest) {
        SelectParams(CChainParams::REGTEST);
    } else if (fTestNet) {
        SelectParams(CChainParams::TESTNET);
    } else {
        SelectParams(CChainParams::MAIN);
    }
    return true;
}
<commit_msg>re-parametr<commit_after>// Copyright (c) 2010 Satoshi Nakamoto
// Copyright (c) 2009-2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "assert.h"

#include "chainparams.h"
#include "core.h"
#include "protocol.h"
#include "util.h"

//
// Main network
//

unsigned int pnSeed[] =
{
    0x12345678
};

class CMainParams : public CChainParams {
public:
    CMainParams() {
        // The message start string is designed to be unlikely to occur in normal data.
        pchMessageStart[0] = 0x04;
        pchMessageStart[1] = 0x04;
        pchMessageStart[2] = 0x04;
        pchMessageStart[3] = 0x04;
        nDefaultPort = mydefport;
        nRPCPort = myrpcport;
        bnProofOfWorkLimit = CBigNum(~uint256(0) >> 20);
        nSubsidyHalvingInterval = ihalving;

        // Build the genesis block. Note that the output of the genesis coinbase cannot
        // be spent as it did not originally exist in the database.

        const char* pszTimestamp = "thepszt";
        CTransaction txNew;
        txNew.vin.resize(1);
        txNew.vout.resize(1);
        txNew.vin[0].scriptSig = CScript() << 486604799 << CBigNum(4) << vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));
        txNew.vout[0].nValue = 1 * COIN;
        txNew.vout[0].scriptPubKey = CScript() << ParseHex("") << OP_CHECKSIG;
        genesis.vtx.push_back(txNew);
        genesis.hashPrevBlock = 0;
        genesis.hashMerkleRoot = genesis.BuildMerkleTree();
        genesis.nVersion = 1;
        genesis.nTime    = mygenesist;
        genesis.nBits    = 0x1e0fffff;
        genesis.nNonce   = 0;

        //// debug print
        hashGenesisBlock = genesis.GetHash();
        //while (hashGenesisBlock > bnProofOfWorkLimit.getuint256()){
        //    if (++genesis.nNonce==0) break;
        //    hashGenesisBlock = genesis.GetHash();
        //}

        printf("%s\n", hashGenesisBlock.ToString().c_str());
        printf("%s\n", genesis.hashMerkleRoot.ToString().c_str());
        printf("%x\n", bnProofOfWorkLimit.GetCompact());
        genesis.print();

        assert(hashGenesisBlock == uint256("0x"));
        assert(genesis.hashMerkleRoot == uint256("0x"));

        vSeeds.push_back(CDNSSeedData("someaddress.com or IP addy", "someaddress.com"));

        base58Prefixes[PUBKEY_ADDRESS] = mylater;
        base58Prefixes[SCRIPT_ADDRESS] = 30;
        base58Prefixes[SECRET_KEY] = 224;

        // Convert the pnSeeds array into usable address objects.
        for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++)
        {
            // It'll only connect to one or two seed nodes because once it connects,
            // it'll get a pile of addresses with newer timestamps.
            // Seed nodes are given a random 'last seen time'
            const int64 nTwoDays = 2 * 24 * 60 * 60;
            struct in_addr ip;
            memcpy(&ip, &pnSeed[i], sizeof(ip));
            CAddress addr(CService(ip, GetDefaultPort()));
            addr.nTime = GetTime() - GetRand(nTwoDays) - nTwoDays;
            vFixedSeeds.push_back(addr);
        }
    }

    virtual const CBlock& GenesisBlock() const { return genesis; }
    virtual Network NetworkID() const { return CChainParams::MAIN; }

    virtual const vector<CAddress>& FixedSeeds() const {
        return vFixedSeeds;
    }
protected:
    CBlock genesis;
    vector<CAddress> vFixedSeeds;
};
static CMainParams mainParams;

//
// Testnet (v3)
//
class CTestNetParams : public CMainParams {
public:
    CTestNetParams() {
        // The message start string is designed to be unlikely to occur in normal data.
        pchMessageStart[0] = 0x01;
        pchMessageStart[1] = 0xfe;
        pchMessageStart[2] = 0xfe;
        pchMessageStart[3] = 0x05;
        nDefaultPort = 55534;
        nRPCPort = 55535;
        strDataDir = "testnet";

        // Modify the testnet genesis block so the timestamp is valid for a later start.
        genesis.nTime = 1374901773;
        genesis.nNonce = 1211565;

        //// debug print
        hashGenesisBlock = genesis.GetHash();
        //while (hashGenesisBlock > bnProofOfWorkLimit.getuint256()){
        //    if (++genesis.nNonce==0) break;
        //   hashGenesisBlock = genesis.GetHash();
        //}

        printf("%s\n", hashGenesisBlock.ToString().c_str());
        printf("%s\n", genesis.hashMerkleRoot.ToString().c_str());
        genesis.print();

        vFixedSeeds.clear();
        vSeeds.clear();
        // vSeeds.push_back(CDNSSeedData("abccoin.test", "test.abccoin.org"));

        base58Prefixes[PUBKEY_ADDRESS] = 130;
        base58Prefixes[SCRIPT_ADDRESS] = 30;
        base58Prefixes[SECRET_KEY] = 239;

    }
    virtual Network NetworkID() const { return CChainParams::TESTNET; }
};
static CTestNetParams testNetParams;

//
// Regression test
//
class CRegTestParams : public CTestNetParams {
public:
    CRegTestParams() {
        pchMessageStart[0] = 0xfa;
        pchMessageStart[1] = 0x0f;
        pchMessageStart[2] = 0xa5;
        pchMessageStart[3] = 0x5a;
        nSubsidyHalvingInterval = 150;
        bnProofOfWorkLimit = CBigNum(~uint256(0) >> 1);
        genesis.nTime = 1296688602;
        genesis.nBits = 0x207fffff;
        genesis.nNonce = 3;
        hashGenesisBlock = genesis.GetHash();
        nDefaultPort = 18444;
        strDataDir = "regtest";

        //// debug print
        hashGenesisBlock = genesis.GetHash();
        //while (hashGenesisBlock > bnProofOfWorkLimit.getuint256()){
        //    if (++genesis.nNonce==0) break;
        //    hashGenesisBlock = genesis.GetHash();
        //}

        printf("%s\n", hashGenesisBlock.ToString().c_str());
        printf("%s\n", genesis.hashMerkleRoot.ToString().c_str());
        genesis.print();

        // assert(hashGenesisBlock == uint256("0x13d8d31dde96874006da503dd2b63fa68c698dc823334359e417aa3a92f80433"));

        vSeeds.clear();  // Regtest mode doesn't have any DNS seeds.

        base58Prefixes[PUBKEY_ADDRESS] = 0;
        base58Prefixes[SCRIPT_ADDRESS] = 5;
        base58Prefixes[SECRET_KEY] = 128;
    }

    virtual bool RequireRPCPassword() const { return false; }
    virtual Network NetworkID() const { return CChainParams::REGTEST; }
};
static CRegTestParams regTestParams;

static CChainParams *pCurrentParams = &mainParams;

const CChainParams &Params() {
    return *pCurrentParams;
}

void SelectParams(CChainParams::Network network) {
    switch (network) {
        case CChainParams::MAIN:
            pCurrentParams = &mainParams;
            break;
        case CChainParams::TESTNET:
            pCurrentParams = &testNetParams;
            break;
        case CChainParams::REGTEST:
            pCurrentParams = &regTestParams;
            break;
        default:
            assert(false && "Unimplemented network");
            return;
    }
}

bool SelectParamsFromCommandLine() {
    bool fRegTest = GetBoolArg("-regtest", false);
    bool fTestNet = GetBoolArg("-testnet", false);

    if (fTestNet && fRegTest) {
        return false;
    }

    if (fRegTest) {
        SelectParams(CChainParams::REGTEST);
    } else if (fTestNet) {
        SelectParams(CChainParams::TESTNET);
    } else {
        SelectParams(CChainParams::MAIN);
    }
    return true;
}
<|endoftext|>


<commit_before>#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>

#define MAX_BUF 1024

#include <sstream>
#include <iostream>
#include <string>
#include <chrono>
using namespace std;
#include <boost/property_tree/json_parser.hpp>

const static double PI = 3.14159265;
const static int iConstRound = 60;
const static double iConstRoundLimit = sin(iConstRound*pi/180.0);

static int fd = -1;
#include <signal.h>
#include <stdio.h>
void sigcatch(int) {
	if(fd > 0) {
		close(fd);
	}
	exit(0);
}
int main(int ac,char*av[])
{
	system("rm -f /tmp/mpu.6050.unix.domain");
	if (SIG_ERR == signal(SIGINT, sigcatch)) {
		printf("failed to set signal handler.n");
		exit(1);
	}
     fd = socket( AF_LOCAL, SOCK_DGRAM, 0 );

	struct sockaddr_un addr;
	bzero( &addr, sizeof(addr) );
	addr.sun_family = AF_LOCAL;
	strcpy( addr.sun_path, "/tmp/mpu.6050.unix.domain" );

   int use = 1;
   if (::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &use, sizeof(int)) < 0) {
    perror("setsockopt(SO_REUSEADDR) failed");
   }

	struct timeval timeout;
	timeout.tv_sec = 0;
	timeout.tv_usec = 1000;
   	if (::setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0) {
	    	perror("setsockopt(SO_RCVTIMEO) failed");
   	}

   if(::bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0)
   {

     printf(" cannot bind socket: %d. \n",errno);
     close(fd);

     return 0;

   }

    char buf[MAX_BUF];
    double degree = 90.0;
    if(ac > 1) {
    	degree = ::atof(av[1]);
    }
    degree = std::fabs(degree);
    int iRound = degree/iConstRound;
    double dRemain = degree - (iRound *iConstRound);
    double startDeg = 0.0;
    bool restartBase = true;
    chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
    int msRun = 0;
    // 1000 ms
    while(msRun < 1000) {
    	chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
    	msRun = chrono::duration_cast<chrono::milliseconds>(end - start).count();
    	//printf("msRun=<%d>\n",msRun);

    	socklen_t len = sizeof(addr);
        int ret = ::recvfrom(fd, buf, MAX_BUF, 0, (struct sockaddr *)&addr, &len);
        if(ret>0){
            //printf("Received: %s\n", buf);
            string recvStr(buf,ret);
            //std::cout << recvStr << std::endl;
            std::stringstream ss;
            ss << recvStr;
            try {
            	boost::property_tree::ptree pt;
            	boost::property_tree::read_json(ss, pt);
            	auto current = pt.get<double>("yaw");
            	//std::cout <<  current << std::endl;
            	if(restartBase) {
            		startDeg = current;
            		restartBase = false;
            		continue;
            	}
            	double dRoundRad = 0.0;
            	if(iRound >0) {
            		dRoundRad = iConstRoundLimit;
            	} else {
            		dRoundRad = sin(PI*dRemain/180.0);
            	}
            	double diffDeg = std::fabs(current - startDeg);
            	double diffRad = (PI*diffDeg/180.0);
            	double diff = dRoundRad - sin(diffRad);
            	std::cout <<  "diff=<" << diff <<">"<< std::endl;
            	if(diff <=0) {
            		if(iRound >0) {
            			iRound--;
	            		restartBase = true;
            		}
            		else {
            			break;
            		}
            	}
            } catch(std::exception e) {
            	std::cout << e.what() << std::endl;
            }
        } else if (ret==0){
        	//printf("ret=<%d>\n",ret);
        } else {
        	//printf("ret=<%d>\n",ret);
        }
    }
    close(fd);

    return 0;
}
<commit_msg>Update turn.cpp<commit_after>#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>

#define MAX_BUF 1024

#include <sstream>
#include <iostream>
#include <string>
#include <chrono>
using namespace std;
#include <boost/property_tree/json_parser.hpp>

const static double PI = 3.14159265;
const static int iConstRound = 60;
const static double iConstRoundLimit = sin(iConstRound*PI/180.0);

static int fd = -1;
#include <signal.h>
#include <stdio.h>
void sigcatch(int) {
	if(fd > 0) {
		close(fd);
	}
	exit(0);
}
int main(int ac,char*av[])
{
	system("rm -f /tmp/mpu.6050.unix.domain");
	if (SIG_ERR == signal(SIGINT, sigcatch)) {
		printf("failed to set signal handler.n");
		exit(1);
	}
     fd = socket( AF_LOCAL, SOCK_DGRAM, 0 );

	struct sockaddr_un addr;
	bzero( &addr, sizeof(addr) );
	addr.sun_family = AF_LOCAL;
	strcpy( addr.sun_path, "/tmp/mpu.6050.unix.domain" );

   int use = 1;
   if (::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &use, sizeof(int)) < 0) {
    perror("setsockopt(SO_REUSEADDR) failed");
   }

	struct timeval timeout;
	timeout.tv_sec = 0;
	timeout.tv_usec = 1000;
   	if (::setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0) {
	    	perror("setsockopt(SO_RCVTIMEO) failed");
   	}

   if(::bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0)
   {

     printf(" cannot bind socket: %d. \n",errno);
     close(fd);

     return 0;

   }

    char buf[MAX_BUF];
    double degree = 90.0;
    if(ac > 1) {
    	degree = ::atof(av[1]);
    }
    degree = std::fabs(degree);
    int iRound = degree/iConstRound;
    double dRemain = degree - (iRound *iConstRound);
    double startDeg = 0.0;
    bool restartBase = true;
    chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
    int msRun = 0;
    // 1000 ms
    while(msRun < 1000) {
    	chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
    	msRun = chrono::duration_cast<chrono::milliseconds>(end - start).count();
    	//printf("msRun=<%d>\n",msRun);

    	socklen_t len = sizeof(addr);
        int ret = ::recvfrom(fd, buf, MAX_BUF, 0, (struct sockaddr *)&addr, &len);
        if(ret>0){
            //printf("Received: %s\n", buf);
            string recvStr(buf,ret);
            //std::cout << recvStr << std::endl;
            std::stringstream ss;
            ss << recvStr;
            try {
            	boost::property_tree::ptree pt;
            	boost::property_tree::read_json(ss, pt);
            	auto current = pt.get<double>("yaw");
            	//std::cout <<  current << std::endl;
            	if(restartBase) {
            		startDeg = current;
            		restartBase = false;
            		continue;
            	}
            	double dRoundRad = 0.0;
            	if(iRound >0) {
            		dRoundRad = iConstRoundLimit;
            	} else {
            		dRoundRad = sin(PI*dRemain/180.0);
            	}
            	double diffDeg = std::fabs(current - startDeg);
            	double diffRad = (PI*diffDeg/180.0);
            	double diff = dRoundRad - sin(diffRad);
            	std::cout <<  "diff=<" << diff <<">"<< std::endl;
            	if(diff <=0) {
            		if(iRound >0) {
            			iRound--;
	            		restartBase = true;
            		}
            		else {
            			break;
            		}
            	}
            } catch(std::exception e) {
            	std::cout << e.what() << std::endl;
            }
        } else if (ret==0){
        	//printf("ret=<%d>\n",ret);
        } else {
        	//printf("ret=<%d>\n",ret);
        }
    }
    close(fd);

    return 0;
}
<|endoftext|>


<commit_before>c22f9a87-2747-11e6-b183-e0f84713e7b8<commit_msg>I'm done<commit_after>c262d6cf-2747-11e6-9a2b-e0f84713e7b8<|endoftext|>


<commit_before>7c98d651-2749-11e6-8dfc-e0f84713e7b8<commit_msg>( ͡° ͜ʖ ͡°)<commit_after>7ca8bafd-2749-11e6-8f3a-e0f84713e7b8<|endoftext|>


<commit_before>9d470c0c-ad58-11e7-be7e-ac87a332f658<commit_msg>Initial commit.2<commit_after>9db38cd9-ad58-11e7-98b8-ac87a332f658<|endoftext|>


<commit_before>#include "crt.h"
#include "map.h"
#include "node.h"
#include "scanner.h"
#include "token.h"
#include "exceptions.h"
#include <iostream>

namespace YAML
{
	Map::Map()
	{
	}

	Map::~Map()
	{
		Clear();
	}

	void Map::Clear()
	{
		for(node_map::const_iterator it=m_data.begin();it!=m_data.end();++it) {
			delete it->first;
			delete it->second;
		}
		m_data.clear();
	}

	bool Map::GetBegin(std::map <Node *, Node *, ltnode>::const_iterator& it) const
	{
		it = m_data.begin();
		return true;
	}

	bool Map::GetEnd(std::map <Node *, Node *, ltnode>::const_iterator& it) const
	{
		it = m_data.end();
		return true;
	}

	void Map::Parse(Scanner *pScanner, const ParserState& state)
	{
		Clear();

		// split based on start token
		switch(pScanner->peek().type) {
			case TT_BLOCK_MAP_START: ParseBlock(pScanner, state); break;
			case TT_FLOW_MAP_START: ParseFlow(pScanner, state); break;
		}
	}

	void Map::ParseBlock(Scanner *pScanner, const ParserState& state)
	{
		// eat start token
		pScanner->pop();

		while(1) {
			if(pScanner->empty())
				throw ParserException(-1, -1, ErrorMsg::END_OF_MAP);

			Token token = pScanner->peek();
			if(token.type != TT_KEY && token.type != TT_BLOCK_END)
				throw ParserException(token.line, token.column, ErrorMsg::END_OF_MAP);

			pScanner->pop();
			if(token.type == TT_BLOCK_END)
				break;

			Node *pKey = new Node;
			Node *pValue = new Node;

			try {
				// grab key
				pKey->Parse(pScanner, state);

				// now grab value (optional)
				if(!pScanner->empty() && pScanner->peek().type == TT_VALUE) {
					pScanner->pop();
					pValue->Parse(pScanner, state);
				}

				m_data[pKey] = pValue;
			} catch(Exception& e) {
				delete pKey;
				delete pValue;
				throw e;
			}
		}
	}

	void Map::ParseFlow(Scanner *pScanner, const ParserState& state)
	{
		// eat start token
		pScanner->pop();

		while(1) {
			if(pScanner->empty())
				throw ParserException(-1, -1, ErrorMsg::END_OF_MAP_FLOW);

			Token& token = pScanner->peek();
			// first check for end
			if(token.type == TT_FLOW_MAP_END) {
				pScanner->pop();
				break;
			}

			// now it better be a key
			if(token.type != TT_KEY)
				throw ParserException(token.line, token.column, ErrorMsg::END_OF_MAP_FLOW);

			pScanner->pop();

			Node *pKey = new Node;
			Node *pValue = new Node;

			try {
				// grab key
				pKey->Parse(pScanner, state);

				// now grab value (optional)
				if(!pScanner->empty() && pScanner->peek().type == TT_VALUE) {
					pScanner->pop();
					pValue->Parse(pScanner, state);
				}

				// now eat the separator (or could be a map end, which we ignore - but if it's neither, then it's a bad node)
				Token& nextToken = pScanner->peek();
				if(nextToken.type == TT_FLOW_ENTRY)
					pScanner->pop();
				else if(nextToken.type != TT_FLOW_MAP_END)
					throw ParserException(nextToken.line, nextToken.column, ErrorMsg::END_OF_MAP_FLOW);

				m_data[pKey] = pValue;
			} catch(Exception& e) {
				// clean up and rethrow
				delete pKey;
				delete pValue;
				throw e;
			}
		}
	}

	void Map::Write(std::ostream& out, int indent, bool startedLine, bool onlyOneCharOnLine)
	{
		if(startedLine && !onlyOneCharOnLine)
			out << "\n";

		for(node_map::const_iterator it=m_data.begin();it!=m_data.end();++it) {
			if((startedLine && !onlyOneCharOnLine) || it != m_data.begin()) {
				for(int i=0;i<indent;i++)
					out << "  ";
			}

			out << "? ";
			it->first->Write(out, indent + 1, true, it!= m_data.begin() || !startedLine || onlyOneCharOnLine);

			for(int i=0;i<indent;i++)
				out << "  ";
			out << ": ";
			it->second->Write(out, indent + 1, true, true);
		}

		if(m_data.empty())
			out << "\n";
	}

	int Map::Compare(Content *pContent)
	{
		return -pContent->Compare(this);
	}

	int Map::Compare(Map *pMap)
	{
		node_map::const_iterator it = m_data.begin(), jt = pMap->m_data.begin();
		while(1) {
			if(it == m_data.end()) {
				if(jt == pMap->m_data.end())
					return 0;
				else
					return -1;
			}
			if(jt == pMap->m_data.end())
				return 1;

			int cmp = it->first->Compare(*jt->first);
			if(cmp != 0)
				return cmp;

			cmp = it->second->Compare(*jt->second);
			if(cmp != 0)
				return cmp;
		}

		return 0;
	}
}
<commit_msg>Fixed a problem where you lose the exception type on rethrow.<commit_after>#include "crt.h"
#include "map.h"
#include "node.h"
#include "scanner.h"
#include "token.h"
#include "exceptions.h"
#include <iostream>

namespace YAML
{
	Map::Map()
	{
	}

	Map::~Map()
	{
		Clear();
	}

	void Map::Clear()
	{
		for(node_map::const_iterator it=m_data.begin();it!=m_data.end();++it) {
			delete it->first;
			delete it->second;
		}
		m_data.clear();
	}

	bool Map::GetBegin(std::map <Node *, Node *, ltnode>::const_iterator& it) const
	{
		it = m_data.begin();
		return true;
	}

	bool Map::GetEnd(std::map <Node *, Node *, ltnode>::const_iterator& it) const
	{
		it = m_data.end();
		return true;
	}

	void Map::Parse(Scanner *pScanner, const ParserState& state)
	{
		Clear();

		// split based on start token
		switch(pScanner->peek().type) {
			case TT_BLOCK_MAP_START: ParseBlock(pScanner, state); break;
			case TT_FLOW_MAP_START: ParseFlow(pScanner, state); break;
		}
	}

	void Map::ParseBlock(Scanner *pScanner, const ParserState& state)
	{
		// eat start token
		pScanner->pop();

		while(1) {
			if(pScanner->empty())
				throw ParserException(-1, -1, ErrorMsg::END_OF_MAP);

			Token token = pScanner->peek();
			if(token.type != TT_KEY && token.type != TT_BLOCK_END)
				throw ParserException(token.line, token.column, ErrorMsg::END_OF_MAP);

			pScanner->pop();
			if(token.type == TT_BLOCK_END)
				break;

			Node *pKey = new Node;
			Node *pValue = new Node;

			try {
				// grab key
				pKey->Parse(pScanner, state);

				// now grab value (optional)
				if(!pScanner->empty() && pScanner->peek().type == TT_VALUE) {
					pScanner->pop();
					pValue->Parse(pScanner, state);
				}

				m_data[pKey] = pValue;
			} catch(Exception&) {
				delete pKey;
				delete pValue;
				throw;
			}
		}
	}

	void Map::ParseFlow(Scanner *pScanner, const ParserState& state)
	{
		// eat start token
		pScanner->pop();

		while(1) {
			if(pScanner->empty())
				throw ParserException(-1, -1, ErrorMsg::END_OF_MAP_FLOW);

			Token& token = pScanner->peek();
			// first check for end
			if(token.type == TT_FLOW_MAP_END) {
				pScanner->pop();
				break;
			}

			// now it better be a key
			if(token.type != TT_KEY)
				throw ParserException(token.line, token.column, ErrorMsg::END_OF_MAP_FLOW);

			pScanner->pop();

			Node *pKey = new Node;
			Node *pValue = new Node;

			try {
				// grab key
				pKey->Parse(pScanner, state);

				// now grab value (optional)
				if(!pScanner->empty() && pScanner->peek().type == TT_VALUE) {
					pScanner->pop();
					pValue->Parse(pScanner, state);
				}

				// now eat the separator (or could be a map end, which we ignore - but if it's neither, then it's a bad node)
				Token& nextToken = pScanner->peek();
				if(nextToken.type == TT_FLOW_ENTRY)
					pScanner->pop();
				else if(nextToken.type != TT_FLOW_MAP_END)
					throw ParserException(nextToken.line, nextToken.column, ErrorMsg::END_OF_MAP_FLOW);

				m_data[pKey] = pValue;
			} catch(Exception&) {
				// clean up and rethrow
				delete pKey;
				delete pValue;
				throw;
			}
		}
	}

	void Map::Write(std::ostream& out, int indent, bool startedLine, bool onlyOneCharOnLine)
	{
		if(startedLine && !onlyOneCharOnLine)
			out << "\n";

		for(node_map::const_iterator it=m_data.begin();it!=m_data.end();++it) {
			if((startedLine && !onlyOneCharOnLine) || it != m_data.begin()) {
				for(int i=0;i<indent;i++)
					out << "  ";
			}

			out << "? ";
			it->first->Write(out, indent + 1, true, it!= m_data.begin() || !startedLine || onlyOneCharOnLine);

			for(int i=0;i<indent;i++)
				out << "  ";
			out << ": ";
			it->second->Write(out, indent + 1, true, true);
		}

		if(m_data.empty())
			out << "\n";
	}

	int Map::Compare(Content *pContent)
	{
		return -pContent->Compare(this);
	}

	int Map::Compare(Map *pMap)
	{
		node_map::const_iterator it = m_data.begin(), jt = pMap->m_data.begin();
		while(1) {
			if(it == m_data.end()) {
				if(jt == pMap->m_data.end())
					return 0;
				else
					return -1;
			}
			if(jt == pMap->m_data.end())
				return 1;

			int cmp = it->first->Compare(*jt->first);
			if(cmp != 0)
				return cmp;

			cmp = it->second->Compare(*jt->second);
			if(cmp != 0)
				return cmp;
		}

		return 0;
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2009-2012 The Bitcoin developers
// Copyright (c) 2011-2012 Litecoin Developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <boost/assign/list_of.hpp> // for 'map_list_of()'
#include <boost/foreach.hpp>

#include "checkpoints.h"

#include "main.h"
#include "uint256.h"

namespace Checkpoints
{
    typedef std::map<int, uint256> MapCheckpoints;

    //
    // What makes a good checkpoint block?
    // + Is surrounded by blocks with reasonable timestamps
    //   (no blocks before with a timestamp after, none after with
    //    timestamp before)
    // + Contains no strange transactions
    //
    static MapCheckpoints mapCheckpoints =
        boost::assign::map_list_of
        (   0, uint256("0x3d9e5080e63c65fb2dd117ea0330892e450c15b5a59c1a6c4e3fb2a01f16d0db"))
	(   1, uint256("0xaf7f1e670b61d341202dec0e873b079eeabd0b745c91d64a799108e61a4c97c9"))
	( 100, uint256("0x2518c68fb48de031618aef649b969efa4adcadaa6d1673ae0153b657b2b1f14b"))
	( 500, uint256("0x8849fb42e5144e72625b3b4ca2d68ca0c47aaa3ffb4772342bebbb17074f7858"))
        ;

    bool CheckBlock(int nHeight, const uint256& hash)
    {
        if (fTestNet) return true; // Testnet has no checkpoints

        MapCheckpoints::const_iterator i = mapCheckpoints.find(nHeight);
        if (i == mapCheckpoints.end()) return true;
        return hash == i->second;
    }

    int GetTotalBlocksEstimate()
    {
        if (fTestNet) return 0;
        return mapCheckpoints.rbegin()->first;
    }

    CBlockIndex* GetLastCheckpoint(const std::map<uint256, CBlockIndex*>& mapBlockIndex)
    {
        if (fTestNet) return NULL;

        BOOST_REVERSE_FOREACH(const MapCheckpoints::value_type& i, mapCheckpoints)
        {
            const uint256& hash = i.second;
            std::map<uint256, CBlockIndex*>::const_iterator t = mapBlockIndex.find(hash);
            if (t != mapBlockIndex.end())
                return t->second;
        }
        return NULL;
    }
}
<commit_msg>Update checkpoints.cpp<commit_after>// Copyright (c) 2009-2012 The Bitcoin developers
// Copyright (c) 2011-2012 Litecoin Developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <boost/assign/list_of.hpp> // for 'map_list_of()'
#include <boost/foreach.hpp>

#include "checkpoints.h"

#include "main.h"
#include "uint256.h"

namespace Checkpoints
{
    typedef std::map<int, uint256> MapCheckpoints;

    //
    // What makes a good checkpoint block?
    // + Is surrounded by blocks with reasonable timestamps
    //   (no blocks before with a timestamp after, none after with
    //    timestamp before)
    // + Contains no strange transactions
    //
    static MapCheckpoints mapCheckpoints =
        boost::assign::map_list_of
        (    0, uint256("0x3d9e5080e63c65fb2dd117ea0330892e450c15b5a59c1a6c4e3fb2a01f16d0db"))
	(    1, uint256("0xaf7f1e670b61d341202dec0e873b079eeabd0b745c91d64a799108e61a4c97c9"))
	(  100, uint256("0x2518c68fb48de031618aef649b969efa4adcadaa6d1673ae0153b657b2b1f14b"))
	(  500, uint256("0x8849fb42e5144e72625b3b4ca2d68ca0c47aaa3ffb4772342bebbb17074f7858"))
	( 1000, uint256("0x3abf5fa6f0721e6d85085a3f946d62a2d659595d50243fde1aea8cec590f1534")) // End of 2x reward
	( 2000, uint256("0x93d7a286fdeef28898449e7bc6381d67e74e82035bea071944a2156d32adbd8e"))
        ;

    bool CheckBlock(int nHeight, const uint256& hash)
    {
        if (fTestNet) return true; // Testnet has no checkpoints

        MapCheckpoints::const_iterator i = mapCheckpoints.find(nHeight);
        if (i == mapCheckpoints.end()) return true;
        return hash == i->second;
    }

    int GetTotalBlocksEstimate()
    {
        if (fTestNet) return 0;
        return mapCheckpoints.rbegin()->first;
    }

    CBlockIndex* GetLastCheckpoint(const std::map<uint256, CBlockIndex*>& mapBlockIndex)
    {
        if (fTestNet) return NULL;

        BOOST_REVERSE_FOREACH(const MapCheckpoints::value_type& i, mapCheckpoints)
        {
            const uint256& hash = i.second;
            std::map<uint256, CBlockIndex*>::const_iterator t = mapBlockIndex.find(hash);
            if (t != mapBlockIndex.end())
                return t->second;
        }
        return NULL;
    }
}
<|endoftext|>


<commit_before>/*
 * main.cpp
 *
 *  Created on: Oct 9, 2016
 *      Author: Yimin Zhong
 */
#include <iostream>
#include "kernel.h"
#include "bicgstab.h"
#include "gmres.h"
#include "geometry.h"
#include "extrapolation.h"

int main() {
#ifdef RUN_OMP
    omp_set_num_threads(omp_get_max_threads());
#endif
    /*
     * allocating source, target locations and weights
     */
    vector<point> coarseSource, fineSource;
    vector<point> coarseTarget, fineTarget;
    vector<point> coarseTriangle, fineTriangle;
    vector<double> coarseWeight, fineWeight;

    /*
     * cube radius and sphere radius
     */
    double cRadius = 2.0;
    double sRadius = 1.5;

    /*
     * slice x slice grid on each face.
     */
    int slice = 64;

    cubeProjection(coarseSource, coarseWeight, coarseTriangle, cRadius, sRadius, slice);
    coarseTarget = coarseSource;

    vector<double> coarseNormalX(coarseSource.size());
    vector<double> coarseNormalY(coarseSource.size());
    vector<double> coarseNormalZ(coarseSource.size());

    for (int i = 0; i < coarseSource.size(); ++i) {
        coarseNormalX[i] = coarseSource[i].x / sRadius;
        coarseNormalY[i] = coarseSource[i].y / sRadius;
        coarseNormalZ[i] = coarseSource[i].z / sRadius;
    }

    cubeProjection(fineSource, fineWeight, fineTriangle, cRadius, sRadius, 2 * slice);
    fineTarget = fineSource;

    vector<double> fineNormalX(fineSource.size());
    vector<double> fineNormalY(fineSource.size());
    vector<double> fineNormalZ(fineSource.size());

    for (int i = 0; i < fineSource.size(); ++i) {
        fineNormalX[i] = fineSource[i].x / sRadius;
        fineNormalY[i] = fineSource[i].y / sRadius;
        fineNormalZ[i] = fineSource[i].z / sRadius;
    }

    int np = 4;
    int maxPoint = 320;
    int maxLevel = 10;

    double k = 0.03;
    double dE = 80.0;
    double dI = 2.0;

    /*
     * not necessary to handle singularity in function
     */
    auto eval_G0 = [&](point &a, point &b) {
        double d = (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) + (a.z - b.z) * (a.z - b.z);
        double r = sqrt(d);
        return 1.0 / 4 / M_PI / r;
    };

    auto eval_Gk = [&](point &a, point &b) {
        double d = (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) + (a.z - b.z) * (a.z - b.z);
        double r = sqrt(d);
        return exp(-k * r) / 4 / M_PI / r;
    };

    auto eval_pG0x = [&](point &a, point &b) {
        double d = (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) + (a.z - b.z) * (a.z - b.z);
        double r = sqrt(d);
        return -(a.x - b.x) / 4 / M_PI / r / d;
    };

    auto eval_pG0y = [&](point &a, point &b) {
        double d = (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) + (a.z - b.z) * (a.z - b.z);
        double r = sqrt(d);
        return -(a.y - b.y) / 4 / M_PI / r / d;
    };

    auto eval_pG0z = [&](point &a, point &b) {
        double d = (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) + (a.z - b.z) * (a.z - b.z);
        double r = sqrt(d);
        return -(a.z - b.z) / 4 / M_PI / r / d;
    };

    auto eval_pGkx = [&](point &a, point &b) {
        double d = (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) + (a.z - b.z) * (a.z - b.z);
        double r = sqrt(d);
        return -(a.x - b.x) * (k * r + 1) / 4 / M_PI / r / d;
    };

    auto eval_pGky = [&](point &a, point &b) {
        double d = (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) + (a.z - b.z) * (a.z - b.z);
        double r = sqrt(d);
        return -(a.y - b.y) * (k * r + 1) / 4 / M_PI / r / d;
    };

    auto eval_pGkz = [&](point &a, point &b) {
        double d = (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) + (a.z - b.z) * (a.z - b.z);
        double r = sqrt(d);
        return -(a.z - b.z) * (k * r + 1) / 4 / M_PI / r / d;
    };

    auto Mapping = [&](vector<point> &source, vector<point> &target, vector<point> triangle, vector<double> &weight,
                       vector<double> &normalX, vector<double> &normalY, vector<double> &normalZ, VectorXd &phi) {
        int N = (int) source.size();

        assert(phi.rows() == 2 * N);

        kernel G0, Gk, pG0x, pG0y, pG0z, pGkx, pGky, pGkz;
        G0.eval = [&](point &a, point &b) {
            if (a == b) return singularIntegral(a, triangle, sRadius, eval_G0);
            else return eval_G0(a, b);
        };
        Gk.eval = [&](point &a, point &b) {
            if (a == b) return singularIntegral(a, triangle, sRadius, eval_Gk);
            else return eval_Gk(a, b);
        };
        pG0x.eval = [&](point &a, point &b) {
            if (a == b) return singularIntegral(a, triangle, sRadius, eval_pG0x);
            else return eval_pG0x(a, b);
        };
        pG0y.eval = [&](point &a, point &b) {
            if (a == b) return singularIntegral(a, triangle, sRadius, eval_pG0y);
            else return eval_pG0y(a, b);
        };
        pG0z.eval = [&](point &a, point &b) {
            if (a == b) return singularIntegral(a, triangle, sRadius, eval_pG0z);
            else return eval_pG0z(a, b);
        };
        pGkx.eval = [&](point &a, point &b) {
            if (a == b) return singularIntegral(a, triangle, sRadius, eval_pGkx);
            else return eval_pGkx(a, b);
        };
        pGky.eval = [&](point &a, point &b) {
            if (a == b) return singularIntegral(a, triangle, sRadius, eval_pGky);
            else return eval_pGky(a, b);
        };
        pG0z.eval = [&](point &a, point &b) {
            if (a == b) return singularIntegral(a, triangle, sRadius, eval_pGkz);
            else return eval_pGkz(a, b);
        };
        // f = partial phi/partial n
        // g = phi
        // Phi =  g   |  f
        VectorXd f(N);
        VectorXd gX(N), gY(N), gZ(N);
        for (int i = 0; i < N; ++i) {
            f(i) = phi(i + N) * weight[i];
            gX(i) = phi(i) * normalX[i] * weight[i];
            gY(i) = phi(i) * normalY[i] * weight[i];
            gZ(i) = phi(i) * normalZ[i] * weight[i];
        }

        G0.initialize(np, source, target, f, N, N, maxPoint, maxLevel);
        pG0x.initialize(np, source, target, gX, N, N, maxPoint, maxLevel);
        pG0y.initialize(np, source, target, gY, N, N, maxPoint, maxLevel);
        pG0z.initialize(np, source, target, gZ, N, N, maxPoint, maxLevel);

        Gk.initialize(np, source, target, f, N, N, maxPoint, maxLevel);
        pGkx.initialize(np, source, target, gX, N, N, maxPoint, maxLevel);
        pGky.initialize(np, source, target, gY, N, N, maxPoint, maxLevel);
        pGkz.initialize(np, source, target, gZ, N, N, maxPoint, maxLevel);

        VectorXd retG0(N), retGk(N), retpG0X(N), retpG0Y(N), retpG0Z(N), retpGkX(N), retpGkY(N), retpGkZ(N);
        G0.run(retG0);
        Gk.run(retGk);
        pG0x.run(retpG0X);
        pG0y.run(retpG0Y);
        pG0z.run(retpG0Z);
        pGkx.run(retpGkX);
        pGky.run(retpGkY);
        pG0z.run(retpGkZ);

        VectorXd ret(2 * N);
        ret.segment(0, N) = 0.5 * phi.segment(0, N) + retpG0X + retpG0Y + retpG0Z - retG0;
        ret.segment(N, N) = 0.5 * phi.segment(0, N) - retpGkX - retpGkY - retpGkZ + dI / dE * retGk;

        return ret;
    };

    int N = (int) coarseSource.size();
    int M = (int) fineSource.size();
    auto coarseMap = [&](VectorXd &phi) {
        return Mapping(coarseSource, coarseTarget, coarseTriangle, coarseWeight, coarseNormalX, coarseNormalY,
                       coarseNormalZ, phi);
    };

    auto fineMap = [&](VectorXd &phi) {
        return Mapping(fineSource, fineTarget, fineTriangle, fineWeight, fineNormalX, fineNormalY,
                       fineNormalZ, phi);
    };

    VectorXd input(2 * N);
    VectorXd start(2 * N);
    start.setZero();
    for (int i = 0; i < N; ++i) {
        input(i) = 1.0 / dE / 4.0 / M_PI / sRadius / (1 + k * sRadius);
        input(i + N) = -1.0 / dI / 4.0 / M_PI / sRadius / sRadius;
    }

    VectorXd output(2 * N);
    output.setZero();
    for (int i = 0; i < N; ++i) {
        output(i) = 1.0 / dI / 4.0 / M_PI / sRadius;
    }

    gmres(coarseMap, output, start, 10, 40, 1e-7);

    VectorXd input_(2 * M);
    VectorXd start_(2 * M);
    start_.setZero();
    for (int i = 0; i < M; ++i) {
        input_(i) = 1.0 / dE / 4.0 / M_PI / sRadius / (1 + k * sRadius);
        input_(i + M) = -1.0 / dI / 4.0 / M_PI / sRadius / sRadius;
    }

    VectorXd output_(2 * M);
    output_.setZero();
    for (int i = 0; i < M; ++i) {
        output_(i) = 1.0 / dI / 4.0 / M_PI / sRadius;
    }

    gmres(fineMap, output_, start_, 10, 40, 1e-7);

    vector<int> proj;
    projection(proj, coarseSource, fineSource);
    VectorXd ret(2 * N);
    for (int i = 0; i < N; ++i) {
        ret(i) = start_(proj[i]);
        ret(i + N) = start_(M + proj[i]);
    }

    std::cout << "coarse error :" << (start - input).norm() / input.norm() << std::endl;
    std::cout << "fine error: " << (start_ - input_).norm() / input_.norm() << std::endl;
    std::cout << "extrapolation: " << (2 * ret - start - input).norm() / input.norm() << std::endl;

}
<commit_msg>minor change<commit_after>/*
 * main.cpp
 *
 *  Created on: Oct 9, 2016
 *      Author: Yimin Zhong
 */
#include <iostream>
#include "kernel.h"
#include "bicgstab.h"
#include "gmres.h"
#include "geometry.h"
#include "extrapolation.h"

int main() {
#ifdef RUN_OMP
    omp_set_num_threads(omp_get_max_threads());
#endif
    /*
     * allocating source, target locations and weights
     */
    vector<point> coarseSource, fineSource;
    vector<point> coarseTarget, fineTarget;
    vector<point> coarseTriangle, fineTriangle;
    vector<double> coarseWeight, fineWeight;

    /*
     * cube radius and sphere radius
     */
    double cRadius = 2.0;
    double sRadius = 1.5;

    /*
     * slice x slice grid on each face.
     */
    int slice = 16;

    cubeProjection(coarseSource, coarseWeight, coarseTriangle, cRadius, sRadius, slice);
    coarseTarget = coarseSource;

    vector<double> coarseNormalX(coarseSource.size());
    vector<double> coarseNormalY(coarseSource.size());
    vector<double> coarseNormalZ(coarseSource.size());

    for (int i = 0; i < coarseSource.size(); ++i) {
        coarseNormalX[i] = coarseSource[i].x / sRadius;
        coarseNormalY[i] = coarseSource[i].y / sRadius;
        coarseNormalZ[i] = coarseSource[i].z / sRadius;
    }

    cubeProjection(fineSource, fineWeight, fineTriangle, cRadius, sRadius, 2 * slice);
    fineTarget = fineSource;

    vector<double> fineNormalX(fineSource.size());
    vector<double> fineNormalY(fineSource.size());
    vector<double> fineNormalZ(fineSource.size());

    for (int i = 0; i < fineSource.size(); ++i) {
        fineNormalX[i] = fineSource[i].x / sRadius;
        fineNormalY[i] = fineSource[i].y / sRadius;
        fineNormalZ[i] = fineSource[i].z / sRadius;
    }

    int np = 4;
    int maxPoint = 320;
    int maxLevel = 10;

    double k = 0.03;
    double dE = 80.0;
    double dI = 2.0;

    /*
     * not necessary to handle singularity in function
     */
    auto eval_G0 = [&](point &a, point &b) {
        double d = (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) + (a.z - b.z) * (a.z - b.z);
        double r = sqrt(d);
        return 1.0 / 4 / M_PI / r;
    };

    auto eval_Gk = [&](point &a, point &b) {
        double d = (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) + (a.z - b.z) * (a.z - b.z);
        double r = sqrt(d);
        return exp(-k * r) / 4 / M_PI / r;
    };

    auto eval_pG0x = [&](point &a, point &b) {
        double d = (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) + (a.z - b.z) * (a.z - b.z);
        double r = sqrt(d);
        return -(a.x - b.x) / 4 / M_PI / r / d;
    };

    auto eval_pG0y = [&](point &a, point &b) {
        double d = (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) + (a.z - b.z) * (a.z - b.z);
        double r = sqrt(d);
        return -(a.y - b.y) / 4 / M_PI / r / d;
    };

    auto eval_pG0z = [&](point &a, point &b) {
        double d = (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) + (a.z - b.z) * (a.z - b.z);
        double r = sqrt(d);
        return -(a.z - b.z) / 4 / M_PI / r / d;
    };

    auto eval_pGkx = [&](point &a, point &b) {
        double d = (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) + (a.z - b.z) * (a.z - b.z);
        double r = sqrt(d);
        return -(a.x - b.x) * (k * r + 1) / 4 / M_PI / r / d;
    };

    auto eval_pGky = [&](point &a, point &b) {
        double d = (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) + (a.z - b.z) * (a.z - b.z);
        double r = sqrt(d);
        return -(a.y - b.y) * (k * r + 1) / 4 / M_PI / r / d;
    };

    auto eval_pGkz = [&](point &a, point &b) {
        double d = (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) + (a.z - b.z) * (a.z - b.z);
        double r = sqrt(d);
        return -(a.z - b.z) * (k * r + 1) / 4 / M_PI / r / d;
    };

    auto Mapping = [&](vector<point> &source, vector<point> &target, vector<point> triangle, vector<double> &weight,
                       vector<double> &normalX, vector<double> &normalY, vector<double> &normalZ, VectorXd &phi) {
        int N = (int) source.size();

        assert(phi.rows() == 2 * N);

        kernel G0, Gk, pG0x, pG0y, pG0z, pGkx, pGky, pGkz;
        G0.eval = [&](point &a, point &b) {
            if (a == b) return singularIntegral(a, triangle, sRadius, eval_G0);
            else return eval_G0(a, b);
        };
        Gk.eval = [&](point &a, point &b) {
            if (a == b) return singularIntegral(a, triangle, sRadius, eval_Gk);
            else return eval_Gk(a, b);
        };
        pG0x.eval = [&](point &a, point &b) {
            if (a == b) return singularIntegral(a, triangle, sRadius, eval_pG0x);
            else return eval_pG0x(a, b);
        };
        pG0y.eval = [&](point &a, point &b) {
            if (a == b) return singularIntegral(a, triangle, sRadius, eval_pG0y);
            else return eval_pG0y(a, b);
        };
        pG0z.eval = [&](point &a, point &b) {
            if (a == b) return singularIntegral(a, triangle, sRadius, eval_pG0z);
            else return eval_pG0z(a, b);
        };
        pGkx.eval = [&](point &a, point &b) {
            if (a == b) return singularIntegral(a, triangle, sRadius, eval_pGkx);
            else return eval_pGkx(a, b);
        };
        pGky.eval = [&](point &a, point &b) {
            if (a == b) return singularIntegral(a, triangle, sRadius, eval_pGky);
            else return eval_pGky(a, b);
        };
        pG0z.eval = [&](point &a, point &b) {
            if (a == b) return singularIntegral(a, triangle, sRadius, eval_pGkz);
            else return eval_pGkz(a, b);
        };
        // f = partial phi/partial n
        // g = phi
        // Phi =  g   |  f
        VectorXd f(N);
        VectorXd gX(N), gY(N), gZ(N);
        for (int i = 0; i < N; ++i) {
            f(i) = phi(i + N) * weight[i];
            gX(i) = phi(i) * normalX[i] * weight[i];
            gY(i) = phi(i) * normalY[i] * weight[i];
            gZ(i) = phi(i) * normalZ[i] * weight[i];
        }

        G0.initialize(np, source, target, f, N, N, maxPoint, maxLevel);
        pG0x.initialize(np, source, target, gX, N, N, maxPoint, maxLevel);
        pG0y.initialize(np, source, target, gY, N, N, maxPoint, maxLevel);
        pG0z.initialize(np, source, target, gZ, N, N, maxPoint, maxLevel);

        Gk.initialize(np, source, target, f, N, N, maxPoint, maxLevel);
        pGkx.initialize(np, source, target, gX, N, N, maxPoint, maxLevel);
        pGky.initialize(np, source, target, gY, N, N, maxPoint, maxLevel);
        pGkz.initialize(np, source, target, gZ, N, N, maxPoint, maxLevel);

        VectorXd retG0(N), retGk(N), retpG0X(N), retpG0Y(N), retpG0Z(N), retpGkX(N), retpGkY(N), retpGkZ(N);
        G0.run(retG0);
        Gk.run(retGk);
        pG0x.run(retpG0X);
        pG0y.run(retpG0Y);
        pG0z.run(retpG0Z);
        pGkx.run(retpGkX);
        pGky.run(retpGkY);
        pG0z.run(retpGkZ);

        VectorXd ret(2 * N);
        ret.segment(0, N) = 0.5 * phi.segment(0, N) + retpG0X + retpG0Y + retpG0Z - retG0;
        ret.segment(N, N) = 0.5 * phi.segment(0, N) - retpGkX - retpGkY - retpGkZ + dI / dE * retGk;

        return ret;
    };

    int N = (int) coarseSource.size();
    int M = (int) fineSource.size();
    auto coarseMap = [&](VectorXd &phi) {
        return Mapping(coarseSource, coarseTarget, coarseTriangle, coarseWeight, coarseNormalX, coarseNormalY,
                       coarseNormalZ, phi);
    };

    auto fineMap = [&](VectorXd &phi) {
        return Mapping(fineSource, fineTarget, fineTriangle, fineWeight, fineNormalX, fineNormalY,
                       fineNormalZ, phi);
    };

    VectorXd input(2 * N);
    VectorXd start(2 * N);

    for (int i = 0; i < N; ++i) {
        input(i) = 1.0 / dE / 4.0 / M_PI / sRadius / (1 + k * sRadius);
        input(i + N) = -1.0 / dI / 4.0 / M_PI / sRadius / sRadius;
    }

    start = input;

    VectorXd output(2 * N);
    output.setZero();
    for (int i = 0; i < N; ++i) {
        output(i) = 1.0 / dI / 4.0 / M_PI / sRadius;
    }

    gmres(coarseMap, output, start, 60, 40, 1e-7);

    VectorXd input_(2 * M);
    VectorXd start_(2 * M);

    for (int i = 0; i < M; ++i) {
        input_(i) = 1.0 / dE / 4.0 / M_PI / sRadius / (1 + k * sRadius);
        input_(i + M) = -1.0 / dI / 4.0 / M_PI / sRadius / sRadius;
    }

    start_ = input_;

    VectorXd output_(2 * M);
    output_.setZero();
    for (int i = 0; i < M; ++i) {
        output_(i) = 1.0 / dI / 4.0 / M_PI / sRadius;
    }

    gmres(fineMap, output_, start_, 60, 40, 1e-7);

    vector<int> proj;
    projection(proj, coarseSource, fineSource);
    VectorXd ret(2 * N);
    for (int i = 0; i < N; ++i) {
        ret(i) = start_(proj[i]);
        ret(i + N) = start_(M + proj[i]);
    }

    std::cout << "coarse error :" << (start - input).norm() / input.norm() << std::endl;
    std::cout << "fine error: " << (start_ - input_).norm() / input_.norm() << std::endl;
    std::cout << "extrapolation: " << (2 * ret - start - input).norm() / input.norm() << std::endl;

}
<|endoftext|>