text:
// Copyright (C) 2009-2012 Lorenzo Caminiti
// Distributed under the Boost Software License, Version 1.0
// (see accompanying file LICENSE_1_0.txt or a copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Home at http://www.boost.org/libs/local_function

#include <boost/config.hpp>
#ifdef BOOST_NO_CXX11_LAMBDAS
#   error "lambda functions required"
#else

#include <boost/noncopyable.hpp>
#include <cassert>

//[noncopyable_cxx11_lambda_error
struct n: boost::noncopyable {
    int i;
    n(int _i): i(_i) {}
};

int main(void) {
    n x(-1);

    auto f = [x](void) {    // Error: x is non-copyable, but if
        assert(x.i == -1);  // bind `&x` then `x` is not constant.
    };
    f();

    return 0;
}
//]

#endif // LAMBDAS

ext: cpp


text:
// Copyright 2016-2019 Doug Moen
// Licensed under the Apache License, version 2.0
// See accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0

#include <cctype>
#include <iostream>
#include <typeinfo>
#include <boost/core/demangle.hpp>
#include <libcurv/context.h>
#include <libcurv/die.h>
#include <libcurv/dtostr.h>
#include <libcurv/exception.h>
#include <libcurv/function.h>
#include <libcurv/sc_compiler.h>
#include <libcurv/sc_context.h>
#include <libcurv/math.h>
#include <libcurv/meaning.h>
#include <libcurv/optimizer.h>
#include <libcurv/picker.h>
#include <libcurv/reactive.h>
#include <libcurv/system.h>
#include <libcurv/typeconv.h>

namespace curv {

struct SC_Data_Ref : public Operation
{
    SC_Value val_;
    SC_Data_Ref(Shared<const Phrase> src, SC_Value v)
    : Operation(std::move(src)), val_(v)
    {}
    SC_Value sc_eval(SC_Frame&) const override { return val_; }
    void exec(Frame&, Executor&) const override { }
};

// This is the main entry point into the Shape Compiler.
void
SC_Compiler::define_function(
    const char* name, SC_Type param_type, SC_Type result_type,
    Shared<const Function> func, const Context& cx)
{
    define_function(
        name,
        std::vector<SC_Type>{param_type},
        result_type,
        func,
        cx);
}

void
SC_Compiler::define_function(
    const char* name,
    std::vector<SC_Type> param_types,
    SC_Type result_type,
    Shared<const Function> func,
    const Context& cx)
{
    begin_function();

    // function prologue
    if (target_ == SC_Target::cpp)
        out_ << "extern \"C\" void " << name << "(";
    else
        out_ << result_type << " " << name << "(";
    bool first = true;
    std::vector<SC_Value> params;
    int n = 0;
    for (auto& ty : param_types) {
        params.push_back(newvalue(ty));
        if (!first) out_ << ", ";
        first = false;
        if (target_ == SC_Target::cpp)
            out_ << "const " << ty << "* param" << n++;
        else
            out_ << ty << " " << params.back();
    }
    if (target_ == SC_Target::cpp) {
        if (!first) out_ << ", ";
        out_ << result_type << "* result)\n";
    } else
        out_ << ")\n";
    out_ << "{\n";
    if (target_ == SC_Target::cpp) {
        n = 0;
        for (unsigned i = 0; i < params.size(); ++i) {
            out_ << "  " << param_types[i] << " " << params[i]
                 << " = *param" << n++ << ";\n";
        }
    }

    // function body
    auto f = SC_Frame::make(0, *this, &cx, nullptr, nullptr);
    Shared<Operation> arg_expr;
    if (params.size() == 1)
        arg_expr = make<SC_Data_Ref>(nullptr, params[0]);
    else {
        auto param_list = List_Expr::make(params.size(),nullptr);
        for (unsigned i = 0; i < params.size(); ++i) {
            param_list->at(i) = make<SC_Data_Ref>(nullptr, params[i]);
        }
        arg_expr = std::move(param_list);
    }
    auto result = func->sc_call_expr(*arg_expr, nullptr, *f);
    if (result.type != result_type) {
        throw Exception(cx, stringify(name," function returns ",result.type));
    }
    end_function();

    // function epilogue
    if (target_ == SC_Target::cpp) {
        out_ << "  *result = " << result << ";\n";
    } else {
        out_ << "  return " << result << ";\n";
    }
    out_ << "}\n";
}

void
SC_Compiler::begin_function()
{
    valcount_ = 0;
    valcache_.clear();
    opcaches_.clear();
    opcaches_.emplace_back(Op_Cache{});
    constants_.str("");
    body_.str("");
}

void
SC_Compiler::end_function()
{
    out_ << "  /* constants */\n";
    out_ << constants_.str();
    out_ << "  /* body */\n";
    out_ << body_.str();
}

SC_Value sc_call_unary_numeric(SC_Frame& f, const char* name)
{
    auto arg = f[0];
    if (!arg.type.is_numeric())
        throw Exception(At_SC_Arg(0, f),
            stringify(name,": argument is not numeric"));
    auto result = f.sc_.newvalue(arg.type);
    f.sc_.out()<<"  "<<arg.type<<" "<<result<<" = "<<name<<"("<<arg<<");\n";
    return result;
}

struct Set_Purity
{
    SC_Compiler& sc_;
    bool previous_purity_;
    Set_Purity(SC_Compiler& sc, bool purity)
    :
        sc_(sc),
        previous_purity_(sc.in_constants_)
    {
        sc_.in_constants_ = purity;
    }
    ~Set_Purity()
    {
        sc_.in_constants_ = previous_purity_;
    }
};

// Wrapper for Operation::sc_eval(f), does common subexpression elimination.
SC_Value sc_eval_op(SC_Frame& f, const Operation& op)
{
#if OPTIMIZE
    if (!op.pure_) {
        Set_Purity pu(f.sc_, false);
        return op.sc_eval(f);
    }
    // 'op' is a uniform expression, consisting of pure operations at interior
    // nodes and Constants at leaf nodes. There can be no variable references
    // (eg, no Local_Data_Ref ops), other than uniform variables in reactive values.
    // What follows is a limited form of common subexpression elimination
    // which reduces code size when reactive values are used.
    for (Op_Cache& opcache : f.sc_.opcaches_) {
        auto cached = opcache.find(share(op));
        if (cached != opcache.end())
            return cached->second;
    }
    Set_Purity pu(f.sc_, true);
    auto val = op.sc_eval(f);
    f.sc_.opcaches_.back()[share(op)] = val;
    return val;
#else
    return op.sc_eval(f);
#endif
}

SC_Value sc_eval_expr(SC_Frame& f, const Operation& op, SC_Type type)
{
    SC_Value arg = sc_eval_op(f, op);
    if (arg.type != type) {
        throw Exception(At_SC_Phrase(op.syntax_, f),
            stringify("wrong argument type: expected ",type,", got ",arg.type));
    }
    return arg;
}

SC_Value sc_eval_bool(SC_Frame& f, const Operation& op)
{
    SC_Value arg = sc_eval_op(f, op);
    if (arg.type != SC_Type::Bool() && arg.type != SC_Type::Bool32()) {
        throw Exception(At_SC_Phrase(op.syntax_, f), stringify(
            "wrong argument type: expected Bool or Bool32, got ",arg.type));
    }
    return arg;
}

void
sc_put_list(
    const List& list, SC_Type ty,
    const At_SC_Phrase& cx, std::ostream& out);

// Write a value to 'out' as a GLSL/C++ initializer expression.
// As a side effect, write GLSL code to f.out when evaluating reactive values.
// At present, reactive values can occur anywhere in an array initializer.
void
sc_put_value(Value val, SC_Type ty, const At_SC_Phrase& cx, std::ostream& out)
{
    if (auto re = val.dycast<Reactive_Expression>()) {
        auto f2 = SC_Frame::make(0, cx.call_frame_.sc_, nullptr,
            &cx.call_frame_, &*cx.phrase_);
        auto result = sc_eval_op(*f2, *re->expr_);
        out << result;
    }
    else if (auto uv = val.dycast<Uniform_Variable>()) {
        out << uv->identifier_;
    }
    else if (ty == SC_Type::Num()) {
        double num = val.to_num(cx);
        out << dfmt(num, dfmt::EXPR);
    }
    else if (ty == SC_Type::Bool()) {
        bool b = val.to_bool(cx);
        out << (b ? "true" : "false");
    }
    else if (ty == SC_Type::Bool32()) {
        Shared<const List> bl = val.to<const List>(cx);
        unsigned bn = bool32_to_nat(bl, cx);
        out << bn << "u";
    }
    else if (ty.is_any_vec()) {
        Shared<const List> list = val.to<const List>(cx);
        list->assert_size(ty.count(), cx);
        out << ty << "(";
        sc_put_list(*list, ty.abase(), cx, out);
        out << ")";
    }
    else if (ty.rank_ > 0) {
        auto list = val.to<List>(cx);
        list->assert_size(ty.dim1_, cx);
        sc_put_list(*list, ty.abase(), cx, out);
    }
    else {
        throw Exception(cx, stringify(
            "internal error at sc_put_value: ", val, ": ", ty));
    }
}

void
sc_put_list(
    const List& list, SC_Type ety,
    const At_SC_Phrase& cx, std::ostream& out)
{
    bool first = true;
    for (auto e : list) {
        if (!first) out << ",";
        first = false;
        sc_put_value(e, ety, cx, out);
    }
}

SC_Value sc_eval_const(SC_Frame& f, Value val, const Phrase& syntax)
{
#if OPTIMIZE
    auto cached = f.sc_.valcache_.find(val);
    if (cached != f.sc_.valcache_.end())
        return cached->second;
#endif
    Set_Purity pu(f.sc_, true);
    At_SC_Phrase cx(share(syntax), f);

    auto ty = sc_type_of(val);
    if (ty == SC_Type::Any()) {
        throw Exception(At_SC_Phrase(share(syntax), f),
            stringify("value ",val," is not supported "));
    }

    String_Builder init;
    sc_put_value(val, ty, cx, init);
    auto initstr = init.get_string();
    SC_Value result = f.sc_.newvalue(ty);
    if (ty.rank_ == 0) {
        f.sc_.out()
            << "  " << ty << " " << result << " = "
            << *initstr << ";\n";
    } else {
        SC_Type ety = ty;
        ety.rank_ = 0;
        if (f.sc_.target_ == SC_Target::cpp) {
            f.sc_.out() << "  " << ety << " " << result << "[] = {"
                << *initstr << "};\n";
        } else {
            f.sc_.out() << "  " << ty << " " << result << " = " << ty << "("
                << *initstr << ");\n";
        }
    }

    f.sc_.valcache_[val] = result;
    return result;
}

SC_Value Operation::sc_eval(SC_Frame& f) const
{
    throw Exception(At_SC_Phrase(syntax_, f), stringify(
        "this expression is not supported: ",
        boost::core::demangle(typeid(*this).name())));
}

void Operation::sc_exec(SC_Frame& f) const
{
    throw Exception(At_SC_Phrase(syntax_, f), stringify(
        "this action is not supported: ",
        boost::core::demangle(typeid(*this).name())));
}

SC_Value Constant::sc_eval(SC_Frame& f) const
{
    return sc_eval_const(f, value_, *syntax_);
}

SC_Value Negative_Expr::sc_eval(SC_Frame& f) const
{
    auto x = sc_eval_op(f, *arg_);
    if (!x.type.is_numeric())
        throw Exception(At_SC_Phrase(arg_->syntax_, f),
            "argument not numeric");
    SC_Value result = f.sc_.newvalue(x.type);
    f.sc_.out()<<"  "<<x.type<<" "<<result<<" = -"<<x<< ";\n";
    return result;
}

void sc_put_as(SC_Frame& f, SC_Value val, const Context& cx, SC_Type type)
{
    if (val.type == type) {
        f.sc_.out() << val;
        return;
    }
    if (val.type == SC_Type::Num()) {
        if (sc_type_count(type) > 1) {
            f.sc_.out() << type << "(";
            bool first = true;
            for (unsigned i = 0; i < sc_type_count(type); ++i) {
                if (!first) f.sc_.out() << ",";
                f.sc_.out() << val;
                first = false;
            }
            f.sc_.out() << ")";
            return;
        }
    }
    throw Exception(cx, stringify("can't convert ",val.type," to ",type));
}

SC_Value
sc_arith_expr(SC_Frame& f, const Phrase& syntax,
    const Operation& xexpr, const char* op, const Operation& yexpr)
{
    auto x = sc_eval_op(f, xexpr);
    auto y = sc_eval_op(f, yexpr);

    SC_Type rtype = SC_Type::Bool();
    if (x.type == y.type)
        rtype = x.type;
    else if (x.type == SC_Type::Num())
        rtype = y.type;
    else if (y.type == SC_Type::Num())
        rtype = x.type;
    if (rtype == SC_Type::Bool())
        throw Exception(At_SC_Phrase(share(syntax), f),
            stringify("domain error: ",x.type,op,y.type));

    SC_Value result = f.sc_.newvalue(rtype);
    f.sc_.out() <<"  "<<rtype<<" "<<result<<" = ";
    if (isalpha(*op)) {
        f.sc_.out() << op << "(";
        sc_put_as(f, x, At_SC_Phrase(xexpr.syntax_, f), rtype);
        f.sc_.out() << ",";
        sc_put_as(f, y, At_SC_Phrase(yexpr.syntax_, f), rtype);
        f.sc_.out() << ")";
    } else {
        sc_put_as(f, x, At_SC_Phrase(xexpr.syntax_, f), rtype);
        f.sc_.out() << op;
        sc_put_as(f, y, At_SC_Phrase(yexpr.syntax_, f), rtype);
    }
    f.sc_.out() << ";\n";
    return result;
}

SC_Value Add_Expr::sc_eval(SC_Frame& f) const
{
    return sc_arith_expr(f, *syntax_, *arg1_, "+", *arg2_);
}

SC_Value Subtract_Expr::sc_eval(SC_Frame& f) const
{
    return sc_arith_expr(f, *syntax_, *arg1_, "-", *arg2_);
}

SC_Value Multiply_Expr::sc_eval(SC_Frame& f) const
{
    return sc_arith_expr(f, *syntax_, *arg1_, "*", *arg2_);
}

SC_Value Divide_Expr::sc_eval(SC_Frame& f) const
{
    return sc_arith_expr(f, *syntax_, *arg1_, "/", *arg2_);
}

SC_Value Power_Expr::sc_eval(SC_Frame& f) const
{
    return sc_arith_expr(f, *syntax_, *arg1_, "pow", *arg2_);
}

// Evaluate an expression to a constant at SC compile time,
// or abort if it isn't a constant.
Value sc_constify(const Operation& op, SC_Frame& f)
{
    if (auto c = dynamic_cast<const Constant*>(&op))
        return c->value_;
    else if (auto dot = dynamic_cast<const Dot_Expr*>(&op)) {
        Value base = sc_constify(*dot->base_, f);
        if (dot->selector_.id_ != nullptr)
            return base.at(dot->selector_.id_->symbol_,
                At_SC_Phrase(op.syntax_, f));
        else
            throw Exception(At_SC_Phrase(dot->selector_.string_->syntax_, f),
                "not an identifier");
    }
    else if (auto ref = dynamic_cast<const Nonlocal_Data_Ref*>(&op))
        return f.nonlocals_->at(ref->slot_);
    else if (auto ref = dynamic_cast<const Symbolic_Ref*>(&op)) {
        auto b = f.nonlocals_->dictionary_->find(ref->name_);
        assert(b != f.nonlocals_->dictionary_->end());
        return f.nonlocals_->get(b->second);
    }
    else if (auto list = dynamic_cast<const List_Expr*>(&op)) {
        Shared<List> listval = List::make(list->size());
        for (size_t i = 0; i < list->size(); ++i) {
            (*listval)[i] = sc_constify(*(*list)[i], f);
        }
        return {listval};
    } else if (auto neg = dynamic_cast<const Negative_Expr*>(&op)) {
        Value arg = sc_constify(*neg->arg_, f);
        if (arg.is_num())
            return Value(-arg.to_num_unsafe());
    }
    throw Exception(At_SC_Phrase(op.syntax_, f),
        "not a constant");
}

bool sc_try_constify(Operation& op, SC_Frame& f, Value& val)
{
    try {
        val = sc_constify(op, f);
        return true;
    } catch (Exception&) {
        return false;
    }
}

bool sc_try_eval(Operation& op, SC_Frame& f, SC_Value& val)
{
    try {
        val = sc_eval_op(f, op);
        return true;
    } catch (Exception&) {
        return false;
    }
}

SC_Value Block_Op::sc_eval(SC_Frame& f) const
{
    statements_.sc_exec(f);
    return sc_eval_op(f, *body_);
}
void Block_Op::sc_exec(SC_Frame& f) const
{
    statements_.sc_exec(f);
    body_->sc_exec(f);
}

SC_Value Do_Expr::sc_eval(SC_Frame& f) const
{
    actions_->sc_exec(f);
    return sc_eval_op(f, *body_);
}

void Compound_Op_Base::sc_exec(SC_Frame& f) const
{
    for (auto s : *this)
        s->sc_exec(f);
}

void Scope_Executable::sc_exec(SC_Frame& f) const
{
    for (auto action : actions_)
        action->sc_exec(f);
}
void Null_Action::sc_exec(SC_Frame&) const
{
}

void
Local_Locative::sc_print(SC_Frame& f) const
{
    f.sc_.out() << f[slot_];
}

void
Indexed_Locative::sc_print(SC_Frame& f) const
{
    // TODO: ensure that base_ is a vector
    base_->sc_print(f);
    int i = 0;
    // convert index_ to i
    auto list = cast<List_Expr>(index_);
    if (list == nullptr || list->size() != 1)
        throw Exception(At_SC_Phrase(index_->syntax_, f),
            "expected '[index]' expression");
    // i = sc_eval_index_expr() might work if we had an SC_Value for base_
    // TODO: restrict range of i based on size of vector
    Value ival = sc_constify(*list->at(0), f);
    i = ival.to_int(0, 3, At_SC_Phrase(index_->syntax_, f));
    f.sc_.out() << '[' << i << ']';
}

void
Locative::sc_print(SC_Frame& f) const
{
    throw Exception(At_SC_Phrase(syntax_, f), "expression is not assignable");
}

void
Assignment_Action::sc_exec(SC_Frame& f) const
{
    SC_Value val = sc_eval_op(f, *expr_);
    f.sc_.out() << "  ";
    locative_->sc_print(f);
    f.sc_.out() << "="<<val<<";\n";
}
void
Data_Setter::sc_exec(SC_Frame& f) const
{
    assert(module_slot_ == (slot_t)(-1));
    pattern_->sc_exec(*definiens_, f, f);
}

char gl_index_letter(Value k, unsigned vecsize, const Context& cx)
{
    auto num = k.to_num_or_nan();
    if (num == 0.0)
        return 'x';
    if (num == 1.0)
        return 'y';
    if (num == 2.0 && vecsize > 2)
        return 'z';
    if (num == 3.0 && vecsize > 3)
        return 'w';
    throw Exception(cx,
        stringify("got ",k,", expected 0..",vecsize-1));
}

// compile array[i] expression
SC_Value sc_eval_index_expr(SC_Value array, Operation& index, SC_Frame& f)
{
    Value k;
    if (array.type.is_any_vec() && sc_try_constify(index, f, k)) {
        // A vector with a constant index. Swizzling is supported.
        if (auto list = k.dycast<List>()) {
            if (list->size() < 2 || list->size() > 4) {
                throw Exception(At_SC_Phrase(index.syntax_, f),
                    "list index vector must have between 2 and 4 elements");
            }
            char swizzle[5];
            memset(swizzle, 0, 5);
            for (size_t i = 0; i <list->size(); ++i) {
                swizzle[i] = gl_index_letter((*list)[i],
                    array.type.count(),
                    At_Index(i, At_SC_Phrase(index.syntax_, f)));
            }
            SC_Value result =
                f.sc_.newvalue(
                    SC_Type::Any_Vec(array.type.abase(), list->size()));
            f.sc_.out() << "  " << result.type << " "<< result<<" = ";
            if (f.sc_.target_ == SC_Target::glsl) {
                // use GLSL swizzle syntax: v.xyz
                f.sc_.out() <<array<<"."<<swizzle;
            } else {
                // fall back to a vector constructor: vec3(v.x,v.y,v.z)
                f.sc_.out() << result.type << "(";
                bool first = true;
                for (size_t i = 0; i < list->size(); ++i) {
                    if (!first)
                        f.sc_.out() << ",";
                    first = false;
                    f.sc_.out() << array << "." << swizzle[i];
                }
                f.sc_.out() << ")";
            }
            f.sc_.out() <<";\n";
            return result;
        }
        const char* arg2 = nullptr;
        auto num = k.to_num_or_nan();
        if (num == 0.0)
            arg2 = ".x";
        else if (num == 1.0)
            arg2 = ".y";
        else if (num == 2.0 && array.type.count() > 2)
            arg2 = ".z";
        else if (num == 3.0 && array.type.count() > 3)
            arg2 = ".w";
        if (arg2 == nullptr)
            throw Exception(At_SC_Phrase(index.syntax_, f),
                stringify("got ",k,", expected 0..",
                    array.type.count()-1));

        SC_Value result = f.sc_.newvalue(array.type.abase());
        f.sc_.out() << "  " << result.type << " " << result << " = "
            << array << arg2 <<";\n";
        return result;
    }
    // An array of numbers, indexed with a number.
    if (array.type.rank_ > 1) {
        throw Exception(At_SC_Phrase(index.syntax_,f), stringify(
            "can't index a ", array.type.rank_, "D array of ",
            SC_Type(array.type.base_type_), " with a single index"));
    }
    auto ix = sc_eval_expr(f, index, SC_Type::Num());
    SC_Value result = f.sc_.newvalue(array.type.abase());
    f.sc_.out() << "  " << result.type << " " << result << " = "
             << array << "[int(" << ix << ")];\n";
    return result;
}

// compile array[i,j] expression
SC_Value sc_eval_index2_expr(
    SC_Value array, Operation& op_ix1, Operation& op_ix2, SC_Frame& f,
    const Context& acx)
{
    auto ix1 = sc_eval_expr(f, op_ix1, SC_Type::Num());
    auto ix2 = sc_eval_expr(f, op_ix2, SC_Type::Num());
    if (array.type.rank_ == 2) {
        // 2D array of number or vector. Not supported by GLSL 1.5,
        // so we emulate this type using a 1D array.
        // Index value must be [i,j], can't use a single index.
        SC_Value result = f.sc_.newvalue({array.type.base_type_});
        f.sc_.out() << "  " << result.type << " " << result << " = " << array
                 << "[int(" << ix1 << ")*" << array.type.dim2_
                 << "+" << "int(" << ix2 << ")];\n";
        return result;
    }
    if (array.type.rank_ == 1 && array.type.base_info().rank == 1) {
        // 1D array of vector.
        SC_Value result = f.sc_.newvalue(SC_Type::Num());
        f.sc_.out() << "  " << result.type << " " << result << " = " << array
                 << "[int(" << ix1 << ")]"
                 << "[int(" << ix2 << ")];\n";
        return result;
    }
    throw Exception(acx, "2 indexes (a[i,j]) not supported for this array");
}

// compile array[i,j,k] expression
SC_Value sc_eval_index3_expr(
    SC_Value array, Operation& op_ix1, Operation& op_ix2, Operation& op_ix3,
    SC_Frame& f, const Context& acx)
{
    if (array.type.rank_ == 2 && array.type.base_info().rank == 1) {
        // 2D array of vector.
        auto ix1 = sc_eval_expr(f, op_ix1, SC_Type::Num());
        auto ix2 = sc_eval_expr(f, op_ix2, SC_Type::Num());
        auto ix3 = sc_eval_expr(f, op_ix3, SC_Type::Num());
        SC_Value result = f.sc_.newvalue(SC_Type::Num());
        f.sc_.out() << "  " << result.type << " " << result << " = " << array
                 << "[int(" << ix1 << ")*" << array.type.dim2_
                 << "+" << "int(" << ix2 << ")][int(" << ix3 << ")];\n";
        return result;
    }
    throw Exception(acx, "3 indexes (a[i,j,k]) not supported for this array");
}

SC_Value Call_Expr::sc_eval(SC_Frame& f) const
{
    SC_Value scval;
    if (sc_try_eval(*func_, f, scval)) {
        if (!scval.type.is_list())
            throw Exception(At_SC_Phrase(func_->syntax_, f),
                stringify("type ", scval.type, ": not an array or function"));
        auto list = cast<List_Expr>(arg_);
        if (list == nullptr)
            throw Exception(At_SC_Phrase(arg_->syntax_, f),
                "expected '[index]' expression");
        if (list->size() == 1)
            return sc_eval_index_expr(scval, *list->at(0), f);
        if (list->size() == 2)
            return sc_eval_index2_expr(scval, *list->at(0), *list->at(1), f,
                At_SC_Phrase(arg_->syntax_, f));
        if (list->size() == 3)
            return sc_eval_index3_expr(scval,
                *list->at(0), *list->at(1), *list->at(2),
                f, At_SC_Phrase(arg_->syntax_, f));
    }
    Value val = sc_constify(*func_, f);
    Value v = val;
    for (;;) {
        if (auto func = v.dycast<Function>()) {
            return func->sc_call_expr(*arg_, syntax_, f);
        }
        if (auto r = v.dycast<Record>()) {
            static Symbol_Ref call_key = make_symbol("call");
            if (r->hasfield(call_key)) {
                v = r->getfield(call_key,At_SC_Phrase(func_->syntax_,f));
                continue;
            }
        }
        break;
    }
    throw Exception(At_SC_Phrase(func_->syntax_, f),
        stringify("",val," is not an array or function"));
}

SC_Value Local_Data_Ref::sc_eval(SC_Frame& f) const
{
    return f[slot_];
}

SC_Value Nonlocal_Data_Ref::sc_eval(SC_Frame& f) const
{
    return sc_eval_const(f, f.nonlocals_->at(slot_), *syntax_);
}
SC_Value Symbolic_Ref::sc_eval(SC_Frame& f) const
{
    auto b = f.nonlocals_->dictionary_->find(name_);
    assert(b != f.nonlocals_->dictionary_->end());
    Value val = f.nonlocals_->get(b->second);
    return sc_eval_const(f, val, *syntax_);
}

SC_Value List_Expr_Base::sc_eval(SC_Frame& f) const
{
    if (this->size() >= 2 && this->size() <= 4) {
        SC_Value elem[4];
        for (unsigned i = 0; i < this->size(); ++i) {
            elem[i] = sc_eval_op(f, *this->at(i));
            SC_Type etype = elem[i].type;
            if (etype != SC_Type::Num() && etype != SC_Type::Bool()
                && etype != SC_Type::Bool32())
            {
                throw Exception(At_SC_Phrase(this->at(0)->syntax_, f),
                    "element of list must have type Num, Bool or Bool32");
            }
            if (i > 0 && etype != elem[0].type) {
                throw Exception(At_SC_Phrase(this->at(i)->syntax_, f),
                    "elements of list must have uniform type");
            }
        }
        SC_Type atype;
        if (elem[0].type == SC_Type::Num())
            atype = SC_Type::Vec(this->size());
        else if (elem[0].type == SC_Type::Bool())
            atype = SC_Type::Bool(this->size());
        else if (elem[0].type == SC_Type::Bool32())
            atype = SC_Type::Bool32(this->size());
        SC_Value result = f.sc_.newvalue(atype);
        f.sc_.out() << "  " << atype << " " << result << " = " << atype << "(";
        bool first = true;
        for (unsigned i = 0; i < this->size(); ++i) {
            if (!first) f.sc_.out() << ",";
            first = false;
            f.sc_.out() << elem[i];
        }
        f.sc_.out() << ");\n";
        return result;
    }
    Value val = sc_constify(*this, f);
    return sc_eval_const(f, val, *syntax_);
}

SC_Value Not_Expr::sc_eval(SC_Frame& f) const
{
    auto arg = sc_eval_bool(f, *arg_);
    SC_Value result = f.sc_.newvalue(arg.type);
    f.sc_.out() << "  " << arg.type << " " << result << " = "
        << (arg.type == SC_Type::Bool32() ? "~" : "!")
        << arg << ";\n";
    return result;
}
SC_Value Or_Expr::sc_eval(SC_Frame& f) const
{
    // TODO: change Or to use lazy evaluation.
    auto arg1 = sc_eval_expr(f, *arg1_, SC_Type::Bool());
    auto arg2 = sc_eval_expr(f, *arg2_, SC_Type::Bool());
    SC_Value result = f.sc_.newvalue(SC_Type::Bool());
    f.sc_.out() <<"  bool "<<result<<" =("<<arg1<<" || "<<arg2<<");\n";
    return result;
}
SC_Value And_Expr::sc_eval(SC_Frame& f) const
{
    // TODO: change And to use lazy evaluation.
    auto arg1 = sc_eval_expr(f, *arg1_, SC_Type::Bool());
    auto arg2 = sc_eval_expr(f, *arg2_, SC_Type::Bool());
    SC_Value result = f.sc_.newvalue(SC_Type::Bool());
    f.sc_.out() <<"  bool "<<result<<" =("<<arg1<<" && "<<arg2<<");\n";
    return result;
}
SC_Value If_Else_Op::sc_eval(SC_Frame& f) const
{
    // TODO: change If to use lazy evaluation.
    auto arg1 = sc_eval_expr(f, *arg1_, SC_Type::Bool());
    auto arg2 = sc_eval_op(f, *arg2_);
    auto arg3 = sc_eval_op(f, *arg3_);
    if (arg2.type != arg3.type) {
        throw Exception(At_SC_Phrase(syntax_, f), stringify(
            "if: type mismatch in 'then' and 'else' arms (",
            arg2.type, ",", arg3.type, ")"));
    }
    SC_Value result = f.sc_.newvalue(arg2.type);
    f.sc_.out() <<"  "<<arg2.type<<" "<<result
             <<" =("<<arg1<<" ? "<<arg2<<" : "<<arg3<<");\n";
    return result;
}
void If_Else_Op::sc_exec(SC_Frame& f) const
{
    auto arg1 = sc_eval_expr(f, *arg1_, SC_Type::Bool());
    f.sc_.out() << "  if ("<<arg1<<") {\n";
    arg2_->sc_exec(f);
    f.sc_.out() << "  } else {\n";
    arg3_->sc_exec(f);
    f.sc_.out() << "  }\n";
}
void If_Op::sc_exec(SC_Frame& f) const
{
    auto arg1 = sc_eval_expr(f, *arg1_, SC_Type::Bool());
    f.sc_.out() << "  if ("<<arg1<<") {\n";
    arg2_->sc_exec(f);
    f.sc_.out() << "  }\n";
}
void While_Op::sc_exec(SC_Frame& f) const
{
    f.sc_.opcaches_.emplace_back(Op_Cache{});
    f.sc_.out() << "  while (true) {\n";
    auto cond = sc_eval_expr(f, *cond_, SC_Type::Bool());
    f.sc_.out() << "  if (!"<<cond<<") break;\n";
    body_->sc_exec(f);
    f.sc_.out() << "  }\n";
    f.sc_.opcaches_.pop_back();
}
void For_Op::sc_exec(SC_Frame& f) const
{
  #define RANGE_EXPRESSIONS 1
    auto range = cast<const Range_Expr>(list_);
    if (range == nullptr)
        throw Exception(At_SC_Phrase(list_->syntax_, f),
            "not a range");
  #if RANGE_EXPRESSIONS
    // range arguments are general expressions
    auto first = sc_eval_expr(f, *range->arg1_, SC_Type::Num());
    auto last = sc_eval_expr(f, *range->arg2_, SC_Type::Num());
    auto step = range->arg3_ != nullptr
        ? sc_eval_expr(f, *range->arg3_, SC_Type::Num())
        : sc_eval_const(f, Value{1.0}, *syntax_);
  #else
    // range arguments are constants
    double first = sc_constify(*range->arg1_, f)
        .to_num(At_SC_Phrase(range->arg1_->syntax_, f));
    double last = sc_constify(*range->arg2_, f)
        .to_num(At_SC_Phrase(range->arg2_->syntax_, f));
    double step = range->arg3_ != nullptr
        ? sc_constify(*range->arg3_, f)
          .to_num(At_SC_Phrase(range->arg3_->syntax_, f))
        : 1.0;
  #endif
    auto i = f.sc_.newvalue(SC_Type::Num());
    f.sc_.opcaches_.emplace_back(Op_Cache{});
  #if RANGE_EXPRESSIONS
    f.sc_.out() << "  for (float " << i << "=" << first << ";"
             << i << (range->half_open_ ? "<" : "<=") << last << ";"
             << i << "+=" << step << ") {\n";
  #else
    f.sc_.out() << "  for (float " << i << "=" << dfmt(first, dfmt::EXPR) << ";"
             << i << (range->half_open_ ? "<" : "<=") << dfmt(last, dfmt::EXPR) << ";"
             << i << "+=" << dfmt(step, dfmt::EXPR) << ") {\n";
  #endif
    pattern_->sc_exec(i, At_SC_Phrase(list_->syntax_, f), f);
    if (cond_) {
        auto cond = sc_eval_expr(f, *cond_, SC_Type::Bool());
        f.sc_.out() << "  if (!"<<cond<<") break;\n";
    }
    body_->sc_exec(f);
    f.sc_.out() << "  }\n";
    f.sc_.opcaches_.pop_back();
}
SC_Value Equal_Expr::sc_eval(SC_Frame& f) const
{
    auto a = sc_eval_op(f, *arg1_);
    auto b = sc_eval_op(f, *arg2_);
    if (a.type != b.type || a.type.rank_ > 0) {
        throw Exception(At_SC_Phrase(syntax_, f),
            stringify("domain error: ",a.type," == ",b.type));
    }
    SC_Value result = f.sc_.newvalue(SC_Type::Bool());
    f.sc_.out() <<"  bool "<<result<<" =("<<a<<" == "<<b<<");\n";
    return result;
}
SC_Value Not_Equal_Expr::sc_eval(SC_Frame& f) const
{
    auto a = sc_eval_op(f, *arg1_);
    auto b = sc_eval_op(f, *arg2_);
    if (a.type != b.type || a.type.rank_ > 0) {
        throw Exception(At_SC_Phrase(syntax_, f),
            stringify("domain error: ",a.type," != ",b.type));
    }
    SC_Value result = f.sc_.newvalue(SC_Type::Bool());
    f.sc_.out() <<"  bool "<<result<<" =("<<a<<" != "<<b<<");\n";
    return result;
}
SC_Value Less_Expr::sc_eval(SC_Frame& f) const
{
    auto arg1 = sc_eval_expr(f, *arg1_, SC_Type::Num());
    auto arg2 = sc_eval_expr(f, *arg2_, SC_Type::Num());
    SC_Value result = f.sc_.newvalue(SC_Type::Bool());
    f.sc_.out() <<"  bool "<<result<<" =("<<arg1<<" < "<<arg2<<");\n";
    return result;
}
SC_Value Greater_Expr::sc_eval(SC_Frame& f) const
{
    auto arg1 = sc_eval_expr(f, *arg1_, SC_Type::Num());
    auto arg2 = sc_eval_expr(f, *arg2_, SC_Type::Num());
    SC_Value result = f.sc_.newvalue(SC_Type::Bool());
    f.sc_.out() <<"  bool "<<result<<" =("<<arg1<<" > "<<arg2<<");\n";
    return result;
}
SC_Value Less_Or_Equal_Expr::sc_eval(SC_Frame& f) const
{
    auto arg1 = sc_eval_expr(f, *arg1_, SC_Type::Num());
    auto arg2 = sc_eval_expr(f, *arg2_, SC_Type::Num());
    SC_Value result = f.sc_.newvalue(SC_Type::Bool());
    f.sc_.out() <<"  bool "<<result<<" =("<<arg1<<" <= "<<arg2<<");\n";
    return result;
}
SC_Value Greater_Or_Equal_Expr::sc_eval(SC_Frame& f) const
{
    auto arg1 = sc_eval_expr(f, *arg1_, SC_Type::Num());
    auto arg2 = sc_eval_expr(f, *arg2_, SC_Type::Num());
    SC_Value result = f.sc_.newvalue(SC_Type::Bool());
    f.sc_.out() <<"  bool "<<result<<" =("<<arg1<<" >= "<<arg2<<");\n";
    return result;
}

SC_Value sc_vec_element(SC_Frame& f, SC_Value vec, int i)
{
    SC_Value r = f.sc_.newvalue(vec.type.abase());
    f.sc_.out() << "  " << r.type << " " << r << " = "
        << vec << "[" << i << "];\n";
    return r;
}

} // namespace curv

ext: cc

max_stars_repo_name: daitomanabe/curv

max_issues_repo_name: daitomanabe/curv

max_forks_repo_name: daitomanabe/curv


text:
//
// Copyright (c) 2019-2022 Ruben Perez Hidalgo (rubenperez038 at gmail dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//

#ifndef BOOST_MYSQL_TEST_COMMON_TEST_COMMON_HPP
#define BOOST_MYSQL_TEST_COMMON_TEST_COMMON_HPP

#include <boost/mysql/value.hpp>
#include <boost/mysql/row.hpp>
#include <boost/mysql/connection_params.hpp>
#include <boost/mysql/detail/auxiliar/stringize.hpp>
#include <boost/test/unit_test.hpp>
#include <vector>
#include <algorithm>
#include <ostream>
#include <cassert>

namespace boost {
namespace mysql {
namespace test {

using detail::stringize;

template <class... Types>
std::vector<value> make_value_vector(Types&&... args)
{
    return std::vector<value>{mysql::value(std::forward<Types>(args))...};
}

template <class... Types>
row makerow(Types&&... args)
{
    return row(make_value_vector(std::forward<Types>(args)...), {});
}

inline date makedate(int num_years, unsigned num_months, unsigned num_days)
{
    return date(days(detail::ymd_to_days(
        detail::year_month_day{num_years, num_months, num_days})));
}

inline datetime makedt(int years, unsigned months, unsigned days,
    int hours=0, int mins=0, int secs=0, int micros=0)
{
    return datetime(makedate(years, months, days)) +
           std::chrono::hours(hours) + std::chrono::minutes(mins) +
           std::chrono::seconds(secs) + std::chrono::microseconds(micros);
}

inline time maket(int hours, int mins, int secs, int micros=0)
{
    return std::chrono::hours(hours) + std::chrono::minutes(mins)
         + std::chrono::seconds(secs) + std::chrono::microseconds(micros);
}

template <std::size_t N>
inline boost::string_view makesv(const char (&value) [N])
{
    return detail::make_string_view(value);
}

template <std::size_t N>
inline boost::string_view makesv(const std::uint8_t (&value) [N])
{
    return boost::string_view(reinterpret_cast<const char*>(value), N);
}

inline boost::string_view makesv(const std::uint8_t* value, std::size_t size)
{
    return boost::string_view(reinterpret_cast<const char*>(value), size);
}

inline void validate_string_contains(
    std::string value,
    const std::vector<std::string>& to_check
)
{
    std::transform(value.begin(), value.end(), value.begin(), &tolower);
    for (const auto& elm: to_check)
    {
        BOOST_TEST(value.find(elm) != std::string::npos,
            "Substring '" << elm << "' not found in '" << value << "'");
    }
}

inline void concat(std::vector<std::uint8_t>& lhs, const void* buff, std::size_t size)
{
    auto current_size = lhs.size();
    lhs.resize(current_size + size);
    memcpy(lhs.data() + current_size, buff, size);
}

inline void concat(std::vector<std::uint8_t>& lhs, const std::vector<uint8_t>& rhs)
{
    concat(lhs, rhs.data(), rhs.size());
}

inline std::vector<std::uint8_t> concat_copy(
    std::vector<uint8_t>&& lhs,
    const std::vector<uint8_t>& rhs
)
{
    concat(lhs, rhs);
    return std::move(lhs);
}

inline const char* to_string(ssl_mode m)
{
    switch (m)
    {
    case ssl_mode::disable: return "ssldisable";
    case ssl_mode::enable: return "sslenable";
    case ssl_mode::require: return "sslrequire";
    default: assert(false); return "";
    }
}

inline const char* to_string(detail::protocol_field_type t) noexcept
{
    switch (t)
    {
    case detail::protocol_field_type::decimal: return "decimal";
    case detail::protocol_field_type::tiny: return "tiny";
    case detail::protocol_field_type::short_: return "short_";
    case detail::protocol_field_type::long_: return "long_";
    case detail::protocol_field_type::float_: return "float_";
    case detail::protocol_field_type::double_: return "double_";
    case detail::protocol_field_type::null: return "null";
    case detail::protocol_field_type::timestamp: return "timestamp";
    case detail::protocol_field_type::longlong: return "longlong";
    case detail::protocol_field_type::int24: return "int24";
    case detail::protocol_field_type::date: return "date";
    case detail::protocol_field_type::time: return "time";
    case detail::protocol_field_type::datetime: return "datetime";
    case detail::protocol_field_type::year: return "year";
    case detail::protocol_field_type::varchar: return "varchar";
    case detail::protocol_field_type::bit: return "bit";
    case detail::protocol_field_type::newdecimal: return "newdecimal";
    case detail::protocol_field_type::enum_: return "enum_";
    case detail::protocol_field_type::set: return "set";
    case detail::protocol_field_type::tiny_blob: return "tiny_blob";
    case detail::protocol_field_type::medium_blob: return "medium_blob";
    case detail::protocol_field_type::long_blob: return "long_blob";
    case detail::protocol_field_type::blob: return "blob";
    case detail::protocol_field_type::var_string: return "var_string";
    case detail::protocol_field_type::string: return "string";
    case detail::protocol_field_type::geometry: return "geometry";
    default: return "unknown";
    }
}

} // test

// make protocol_field_type streamable
namespace detail {

inline std::ostream& operator<<(std::ostream& os, protocol_field_type t)
{
    return os << test::to_string(t);
}

} // detail

} // mysql
} // boost

#endif /* TEST_TEST_COMMON_HPP_ */

ext: hpp

max_stars_repo_name: anarthal/mysql-asio

max_issues_repo_name: anarthal/mysql-asio

max_forks_repo_name: anarthal/mysql-asio


text:
#define BOOST_TEST_MODULE uri_codec

#include <boost/test/unit_test.hpp>

#include <uri/schemes/uri/algorithm.hpp>
#include <uri/ios.hpp>

namespace protocol {
    struct default_ {};
} // namespace protocol

using uri_type = uri::basic_uri<protocol::default_>;

BOOST_AUTO_TEST_CASE(encode_uri)
{
    uri_type uri("http",
                 "user:pass",
                 "www.google.com",
                 "8080",
                 "/root/dir",
                 "query",
                 "fragment");
    uri_type encodedUri = encode(uri);

    //BOOST_TEST( encodedUri == uri );
}

max_stars_repo_name: ledocc/uri

max_issues_repo_name: ledocc/uri

max_forks_repo_name: ledocc/uri


text:
#pragma once

#include "dknn/typedefs.hpp"
#include <boost/container/flat_map.hpp>
#include <tuple>

namespace dknn {
  using class_annotated_feature_data_t = std::tuple<feature_class_t, feature_t>;

  using boost::container::flat_map;
  using feature_dataset_t =
    flat_map<feature_id_t, class_annotated_feature_data_t>;
  extern feature_dataset_t __feature_dataset__;

  void load_feature_dataset(std::string filename);
}  // namespace dknn

max_stars_repo_name: didrod/dknn

max_issues_repo_name: didrod/dknn

max_forks_repo_name: didrod/dknn


text:
/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "mitkConnectomicsNetwork.h"
#include <mitkConnectomicsStatisticsCalculator.h>
#include <boost/graph/clustering_coefficient.hpp>
#include <boost/graph/betweenness_centrality.hpp>

/* Constructor and Destructor */
mitk::ConnectomicsNetwork::ConnectomicsNetwork()
: m_IsModified( false )
{
}

mitk::ConnectomicsNetwork::~ConnectomicsNetwork()
{
}

/* Wrapper methods */

bool mitk::ConnectomicsNetwork::EdgeExists(
  mitk::ConnectomicsNetwork::VertexDescriptorType vertexA, mitk::ConnectomicsNetwork::VertexDescriptorType vertexB ) const
{
  return boost::edge(vertexA, vertexB, m_Network ).second;
}

void mitk::ConnectomicsNetwork::IncreaseEdgeWeight(
  mitk::ConnectomicsNetwork::VertexDescriptorType vertexA, mitk::ConnectomicsNetwork::VertexDescriptorType vertexB )
{
  m_Network[ boost::edge(vertexA, vertexB, m_Network ).first ].weight++;

  SetIsModified( true );
}

void mitk::ConnectomicsNetwork::AddEdge(
                                        mitk::ConnectomicsNetwork::VertexDescriptorType vertexA,
                                        mitk::ConnectomicsNetwork::VertexDescriptorType vertexB
                                        )
{
  AddEdge(vertexA, vertexB, m_Network[ vertexA ].id, m_Network[ vertexB ].id );
}

void mitk::ConnectomicsNetwork::AddEdge(
                                        mitk::ConnectomicsNetwork::VertexDescriptorType vertexA,
                                        mitk::ConnectomicsNetwork::VertexDescriptorType vertexB,
                                        int sourceID, int targetID, int weight )
{
  boost::add_edge( vertexA, vertexB, m_Network );
  m_Network[ boost::edge(vertexA, vertexB, m_Network ).first ].sourceId = sourceID;
  m_Network[ boost::edge(vertexA, vertexB, m_Network ).first ].targetId = targetID;
  m_Network[ boost::edge(vertexA, vertexB, m_Network ).first ].weight = weight;
  m_Network[ boost::edge(vertexA, vertexB, m_Network ).first ].edge_weight = 1.0;

  SetIsModified( true );
}

mitk::ConnectomicsNetwork::VertexDescriptorType mitk::ConnectomicsNetwork::AddVertex( int id )
{
  VertexDescriptorType vertex = boost::add_vertex( m_Network );
  m_Network[vertex].id = id;

  SetIsModified( true );

  return vertex;
}

void mitk::ConnectomicsNetwork::SetLabel(
  mitk::ConnectomicsNetwork::VertexDescriptorType vertex, std::string inLabel )
{
  m_Network[vertex].label = inLabel;

  SetIsModified( true );
}

void mitk::ConnectomicsNetwork::SetCoordinates(
  mitk::ConnectomicsNetwork::VertexDescriptorType vertex, std::vector< float > inCoordinates )
{
  m_Network[vertex].coordinates = inCoordinates;

  SetIsModified( true );
}

void mitk::ConnectomicsNetwork::clear()
{
  m_Network.clear();

  SetIsModified( true );
}

/* Superclass methods, that need to be implemented */
void mitk::ConnectomicsNetwork::UpdateOutputInformation()
{

}
void mitk::ConnectomicsNetwork::SetRequestedRegionToLargestPossibleRegion()
{

}
bool mitk::ConnectomicsNetwork::RequestedRegionIsOutsideOfTheBufferedRegion()
{
  return false;
}
bool mitk::ConnectomicsNetwork::VerifyRequestedRegion()
{
  return true;
}
void mitk::ConnectomicsNetwork::SetRequestedRegion(const itk::DataObject * /*data*/ )
{

}

std::vector< mitk::ConnectomicsNetwork::NetworkNode >
mitk::ConnectomicsNetwork::GetVectorOfAllNodes() const
{
  boost::graph_traits<NetworkType>::vertex_iterator iterator, end;

  // sets iterator to start end end to end
  boost::tie(iterator, end) = boost::vertices( m_Network );

  std::vector< NetworkNode > vectorOfNodes;

  for ( ; iterator != end; ++iterator)
  {
    NetworkNode tempNode;

    // the value of an iterator is a descriptor
    tempNode = m_Network[ *iterator ];

    vectorOfNodes.push_back( tempNode );
  }

  return vectorOfNodes;
}

std::vector< mitk::ConnectomicsNetwork::VertexDescriptorType >
mitk::ConnectomicsNetwork::GetVectorOfAllVertexDescriptors() const
{
  boost::graph_traits<NetworkType>::vertex_iterator iterator, end;

  // sets iterator to start end end to end
  boost::tie(iterator, end) = boost::vertices( m_Network );

  std::vector< VertexDescriptorType > vectorOfDescriptors;

  for ( ; iterator != end; ++iterator)
  {
    vectorOfDescriptors.push_back( *iterator );
  }

  return vectorOfDescriptors;
}

std::vector< std::pair<
std::pair< mitk::ConnectomicsNetwork::NetworkNode, mitk::ConnectomicsNetwork::NetworkNode >
, mitk::ConnectomicsNetwork::NetworkEdge > >
mitk::ConnectomicsNetwork::GetVectorOfAllEdges() const
{
  boost::graph_traits<NetworkType>::edge_iterator iterator, end;

  // sets iterator to start end end to end
  boost::tie(iterator, end) = boost::edges( m_Network );

  std::vector<
    std::pair<
    std::pair< NetworkNode, NetworkNode >
    , NetworkEdge
    >
  > vectorOfEdges;

  for ( ; iterator != end; ++iterator)
  {
    NetworkNode sourceNode, targetNode;
    NetworkEdge tempEdge;

    // the value of an iterator is a descriptor
    tempEdge = m_Network[ *iterator ];
    sourceNode = m_Network[ boost::source( *iterator, m_Network ) ];
    targetNode = m_Network[ boost::target( *iterator, m_Network ) ];

    std::pair< NetworkNode, NetworkNode > nodePair( sourceNode, targetNode );
    std::pair< std::pair< NetworkNode, NetworkNode > , NetworkEdge > edgePair( nodePair, tempEdge);
    vectorOfEdges.push_back( edgePair );
  }

  return vectorOfEdges;
}

int mitk::ConnectomicsNetwork::GetNumberOfVertices() const
{
  return boost::num_vertices( m_Network );
}

int mitk::ConnectomicsNetwork::GetNumberOfEdges() const
{
  return boost::num_edges( m_Network );
}

int mitk::ConnectomicsNetwork::GetMaximumWeight() const
{
  int maxWeight( 0 );

  boost::graph_traits<NetworkType>::edge_iterator iterator, end;

  // sets iterator to start end end to end
  boost::tie(iterator, end) = boost::edges( m_Network );

  for ( ; iterator != end; ++iterator)
  {
    int tempWeight;

    // the value of an iterator is a descriptor
    tempWeight = m_Network[ *iterator ].weight;

    if( tempWeight > maxWeight )
    {
      maxWeight = tempWeight;
    }
  }

  return maxWeight;
}

int mitk::ConnectomicsNetwork::GetNumberOfSelfLoops()
{
  int noOfSelfLoops( 0 );

  std::vector< std::pair< std::pair< NetworkNode, NetworkNode > , NetworkEdge > >
    edgeVector =  GetVectorOfAllEdges();

  for( unsigned int index = 0; index < edgeVector.size() ; index++ )
  {
    double sourceX, sourceY, sourceZ, targetX, targetY, targetZ;

    sourceX = edgeVector[ index ].first.first.coordinates[0] ;
    sourceY = edgeVector[ index ].first.first.coordinates[1] ;
    sourceZ = edgeVector[ index ].first.first.coordinates[2] ;
    targetX = edgeVector[ index ].first.second.coordinates[0] ;
    targetY = edgeVector[ index ].first.second.coordinates[1] ;
    targetZ = edgeVector[ index ].first.second.coordinates[2] ;

    // if the coordinates are the same
    if(
      sourceX > ( targetX - 0.01 ) &&
      sourceX < ( targetX + 0.01 ) &&
      sourceY > ( targetY - 0.01 ) &&
      sourceY < ( targetY + 0.01 ) &&
      sourceZ > ( targetZ - 0.01 ) &&
      sourceZ < ( targetZ + 0.01 )
      )
    {
      noOfSelfLoops++;
    }
  }

  return noOfSelfLoops;
}

double mitk::ConnectomicsNetwork::GetAverageDegree()
{
  double vertices = (double) GetNumberOfVertices();
  double edges = (double) GetNumberOfEdges();

  return ( ( edges * 2.0 ) / vertices );
}

double mitk::ConnectomicsNetwork::GetConnectionDensity()
{
  double vertices = (double) GetNumberOfVertices();
  double edges = (double) GetNumberOfEdges();
  double numberOfPossibleEdges = vertices * ( vertices - 1 ) / 2 ;

  return ( edges / numberOfPossibleEdges );
}

std::vector< int > mitk::ConnectomicsNetwork::GetDegreeOfNodes( ) const
{
  std::vector< int > vectorOfDegree;

  boost::graph_traits<NetworkType>::vertex_iterator iterator, end;

  // sets iterator to start end end to end
  boost::tie( iterator, end ) = boost::vertices( m_Network );

  vectorOfDegree.resize( this->GetNumberOfVertices() );

  for ( ; iterator != end; ++iterator)
  {
    // the value of an iterator is a descriptor
    vectorOfDegree[ m_Network[ *iterator ].id ] = GetVectorOfAdjacentNodes( *iterator ).size();
  }
  return vectorOfDegree;
}

std::vector< mitk::ConnectomicsNetwork::VertexDescriptorType >
mitk::ConnectomicsNetwork::GetVectorOfAdjacentNodes( mitk::ConnectomicsNetwork::VertexDescriptorType vertex ) const
{
  std::vector< mitk::ConnectomicsNetwork::VertexDescriptorType > vectorOfAdjacentNodes;

  boost::graph_traits<NetworkType>::adjacency_iterator adjIter, adjEnd;

  boost::tie( adjIter, adjEnd ) = boost::adjacent_vertices( vertex, m_Network);

  for ( ; adjIter != adjEnd; ++adjIter)
  {
    vectorOfAdjacentNodes.push_back( *adjIter );
  }

  return vectorOfAdjacentNodes;
}

int mitk::ConnectomicsNetwork::GetMaximumDegree() const
{
  int maximumDegree( 0 );

  std::vector< int > vectorOfDegree = GetDegreeOfNodes();

  for( unsigned int index( 0 ); index < vectorOfDegree.size(); ++index )
  {
    if( maximumDegree < vectorOfDegree[ index ] )
    {
      maximumDegree = vectorOfDegree[ index ];
    }
  }

  return maximumDegree;
}

std::vector< double > mitk::ConnectomicsNetwork::GetLocalClusteringCoefficients( ) const
{
  std::vector< double > vectorOfClusteringCoefficients;

  typedef boost::graph_traits<NetworkType>::vertex_iterator vertexIter;

  vectorOfClusteringCoefficients.resize( this->GetNumberOfVertices() );

  std::pair<vertexIter, vertexIter> vertexPair;

  //for every vertex calculate the clustering coefficient
  int size = vectorOfClusteringCoefficients.size();
  for (vertexPair = vertices(m_Network); vertexPair.first != vertexPair.second; ++vertexPair.first)
  {
    int index = m_Network[ *vertexPair.first ].id;

    if( index > size )
    {
      MITK_ERROR << "Trying to access out of bounds clustering coefficient";
      continue;
    }

    vectorOfClusteringCoefficients[ index ] =
      boost::clustering_coefficient(m_Network,*vertexPair.first) ;
  }

  return vectorOfClusteringCoefficients;
}

std::vector< double > mitk::ConnectomicsNetwork::GetClusteringCoefficientsByDegree( )
{
  std::vector< double > vectorOfClusteringCoefficients = GetLocalClusteringCoefficients();
  std::vector< int > vectorOfDegree = GetDegreeOfNodes();

  std::vector< double > vectorOfClusteringCoefficientsByDegree;
  vectorOfClusteringCoefficientsByDegree.resize( GetMaximumDegree() + 1, 0 );

  // c_{mean}(k) = frac{1}_{N_{k}} sum_{i in Y(k)} c_{i}
  // where N_{k} is the number of vertices of degree k
  // Y(k) is the set of vertices of degree k
  // c_{i} is the local clustering coefficient of vertex i
  for( unsigned int degree( 0 ); degree < vectorOfClusteringCoefficientsByDegree.size(); ++degree )
  {
    vectorOfClusteringCoefficientsByDegree[ degree ] = 0;
    int n_k( 0 );
    for( unsigned int index( 0 ); index < vectorOfDegree.size(); ++index )
    {
      if( degree == (unsigned int)vectorOfDegree[ index ] )
      {// if in Y( degree )
        vectorOfClusteringCoefficientsByDegree[ degree ] += vectorOfClusteringCoefficients[ index ];
        n_k++;
      }
    }
    if( n_k != 0 )
    {
      vectorOfClusteringCoefficientsByDegree[ degree ] =
        vectorOfClusteringCoefficientsByDegree[ degree ] / n_k;
    }
  }

  return vectorOfClusteringCoefficientsByDegree;
}

double mitk::ConnectomicsNetwork::GetGlobalClusteringCoefficient( )
{
  double globalClusteringCoefficient( 0.0 );

  std::vector< double > vectorOfClusteringCoefficientsByDegree = GetClusteringCoefficientsByDegree();
  std::vector< int > vectorOfDegree = GetDegreeOfNodes();
  std::vector< int > degreeDistribution;
  degreeDistribution.resize( vectorOfClusteringCoefficientsByDegree.size(), 0 );

  int normalizationParameter( 0 );

  for( unsigned int index( 0 ); index < vectorOfDegree.size(); ++index )
  {
    degreeDistribution[ vectorOfDegree[ index ] ]++;
    normalizationParameter++;
  }
  // c_{mean} = sum_{k} P_{k} c_{mean}(k)
  // where P_{k} is the degree distribution
  // k is the degree
  for( unsigned int degree( 0 ); degree < degreeDistribution.size(); ++degree )
  {
    globalClusteringCoefficient +=
      degreeDistribution[ degree ] / ( (double) normalizationParameter)
      * vectorOfClusteringCoefficientsByDegree[ degree ];
  }

  return globalClusteringCoefficient;
}

mitk::ConnectomicsNetwork::NetworkType* mitk::ConnectomicsNetwork::GetBoostGraph()
{
  return &m_Network;
}

void mitk::ConnectomicsNetwork::SetBoostGraph( NetworkType* newGraph )
{
  this->clear();

  m_Network = *newGraph;
  this->SetIsModified( true );
}

void mitk::ConnectomicsNetwork::ImportNetwort( mitk::ConnectomicsNetwork::Pointer source )
{
  typedef std::vector< std::pair< std::pair< NetworkNode, NetworkNode >, NetworkEdge > > EdgeVectorType;
  typedef std::vector< NetworkNode >  VertexVectorType;

  this->clear();

  this->SetGeometry( source->GetGeometry());
  VertexVectorType vertexVector = source->GetVectorOfAllNodes();
  EdgeVectorType edgeVector = source->GetVectorOfAllEdges();
  std::map< int, VertexDescriptorType > idToVertexMap;

  for( unsigned int loop(0); loop < vertexVector.size(); loop++ )
  {
    VertexDescriptorType newVertex = this->AddVertex( vertexVector[ loop ].id );
    this->SetLabel( newVertex, vertexVector[ loop ].label );
    this->SetCoordinates( newVertex, vertexVector[ loop ].coordinates );

    if ( idToVertexMap.count( vertexVector[ loop ].id ) > 0 )
    {
      MITK_ERROR << "Aborting network import, duplicate vertex ID discovered.";
      return;
    }
    idToVertexMap.insert( std::pair< int, VertexDescriptorType >( vertexVector[ loop ].id, newVertex) );
  }

  for( unsigned int loop(0); loop < edgeVector.size(); loop++ )
  {
    VertexDescriptorType source = idToVertexMap.find( edgeVector[ loop ].second.sourceId )->second;
    VertexDescriptorType target = idToVertexMap.find( edgeVector[ loop ].second.targetId )->second;

    this->AddEdge( source, target, edgeVector[ loop ].second.sourceId, edgeVector[ loop ].second.targetId, edgeVector[ loop ].second.weight);
  }

  this->SetIsModified( true );
}

bool mitk::ConnectomicsNetwork::GetIsModified() const
{
  return m_IsModified;
}

void mitk::ConnectomicsNetwork::SetIsModified( bool value)
{
  m_IsModified = value;
}

mitk::ConnectomicsNetwork::NetworkNode mitk::ConnectomicsNetwork::GetNode( VertexDescriptorType vertex ) const
{
  return m_Network[ vertex ];
}

mitk::ConnectomicsNetwork::NetworkEdge mitk::ConnectomicsNetwork::GetEdge( VertexDescriptorType vertexA, VertexDescriptorType vertexB ) const
{
  return m_Network[ boost::edge(vertexA, vertexB, m_Network ).first ];
}

void mitk::ConnectomicsNetwork::UpdateBounds( )
{
  float min = itk::NumericTraits<float>::min();
  float max = itk::NumericTraits<float>::max();
  float bounds[] = {max, min, max, min, max, min};

  std::vector< mitk::ConnectomicsNetwork::NetworkNode > nodeVector = this->GetVectorOfAllNodes();

  if( nodeVector.size() == 0 )
  {
    bounds[0] = 0;
    bounds[1] = 1;
    bounds[2] = 0;
    bounds[3] = 1;
    bounds[4] = 0;
    bounds[5] = 1;
  }

  // for each direction, make certain the point is in between
  for( int index(0), end(nodeVector.size()) ; index < end; index++ )
  {
    for( unsigned int direction(0); direction < nodeVector.at( index ).coordinates.size(); direction++ )
    {
      if( nodeVector.at( index ).coordinates.at(direction) < bounds[ 2 * direction ]  )
      {
        bounds[ 2 * direction ] = nodeVector.at( index ).coordinates.at(direction);
      }

      if( nodeVector.at( index ).coordinates.at(direction) > bounds[ 2 * direction + 1]  )
      {
        bounds[ 2 * direction + 1] = nodeVector.at( index ).coordinates.at(direction);
      }
    }
  }

  // provide some border margin
  for(int i=0; i<=4; i+=2)
  {
    bounds[i] -=10;
  }

  for(int i=1; i<=5; i+=2)
  {
    bounds[i] +=10;
  }

  this->GetGeometry()->SetFloatBounds(bounds);
  this->GetTimeGeometry()->Update();
}

void mitk::ConnectomicsNetwork::PruneUnconnectedSingleNodes()
{
  boost::graph_traits<NetworkType>::vertex_iterator iterator, end;

  // set to true if iterators are invalidated by deleting a vertex
  bool vertexHasBeenRemoved( true );

  // if no vertex has been removed in the last loop, we are done
  while( vertexHasBeenRemoved )
  {
    vertexHasBeenRemoved = false;
    // sets iterator to start and end to end
    boost::tie(iterator, end) = boost::vertices( m_Network );

    for ( ; iterator != end && !vertexHasBeenRemoved; ++iterator)
    {
      // If the node has no adjacent vertices it should be deleted
      if( GetVectorOfAdjacentNodes( *iterator ).size() == 0 )
      {
        vertexHasBeenRemoved = true;
        // this invalidates all iterators
        boost::remove_vertex( *iterator, m_Network );
      }
    }
  }

  UpdateIDs();
}

void mitk::ConnectomicsNetwork::UpdateIDs()
{
  boost::graph_traits<NetworkType>::vertex_iterator v_i, v_end;
  boost::graph_traits<NetworkType>::edge_iterator e_i, e_end;

  // update node ids
  boost::tie( v_i, v_end ) = boost::vertices( m_Network );

  for ( ; v_i != v_end; ++v_i)
  {
    m_Network[*v_i].id = *v_i;
  }

  // update edge information
  boost::tie(e_i, e_end) = boost::edges( m_Network );

  for ( ; e_i != e_end; ++e_i)
  {
    m_Network[ *e_i ].sourceId = m_Network[ boost::source( *e_i, m_Network ) ].id;
    m_Network[ *e_i ].targetId = m_Network[ boost::target( *e_i, m_Network ) ].id;
  }
  this->SetIsModified( true );
}

std::vector< double > mitk::ConnectomicsNetwork::GetNodeBetweennessVector() const
{
  std::vector< double > betweennessVector;

  betweennessVector.clear();
  betweennessVector.resize( this->GetNumberOfVertices() );

  boost::brandes_betweenness_centrality(
    m_Network,
    boost::centrality_map(
    boost::make_iterator_property_map( betweennessVector.begin(), boost::get( &NetworkNode::id, m_Network ), double() )
    ).vertex_index_map( boost::get( &NetworkNode::id, m_Network ) )
    );

  return betweennessVector;
}

std::vector< double > mitk::ConnectomicsNetwork::GetEdgeBetweennessVector() const
{
  // std::map used for convenient initialization
  typedef std::map<EdgeDescriptorType, int> EdgeIndexStdMap;
  EdgeIndexStdMap stdEdgeIndex;
  // associative property map needed for iterator property map-wrapper
  typedef boost::associative_property_map< EdgeIndexStdMap > EdgeIndexMap;
  EdgeIndexMap edgeIndex(stdEdgeIndex);

  boost::graph_traits<NetworkType>::edge_iterator iterator, end;

  // sets iterator to start end end to end
  boost::tie(iterator, end) = boost::edges( m_Network );

  int i(0);
  for ( ; iterator != end; ++iterator, ++i)
  {
    stdEdgeIndex.insert(std::pair< EdgeDescriptorType, int >( *iterator, i));
  }

  // Define EdgeCentralityMap
  std::vector< double > edgeBetweennessVector(boost::num_edges( m_Network ), 0.0);
  // Create the external property map
  boost::iterator_property_map< std::vector< double >::iterator, EdgeIndexMap >
    e_centrality_map(edgeBetweennessVector.begin(), edgeIndex);

  // Define VertexCentralityMap
  typedef boost::property_map< NetworkType, boost::vertex_index_t>::type VertexIndexMap;
  VertexIndexMap vertexIndex = get(boost::vertex_index, m_Network );
  std::vector< double > betweennessVector(boost::num_vertices( m_Network ), 0.0);
  // Create the external property map
  boost::iterator_property_map< std::vector< double >::iterator, VertexIndexMap >
    v_centrality_map(betweennessVector.begin(), vertexIndex);

  boost::brandes_betweenness_centrality( m_Network, v_centrality_map, e_centrality_map );

  return edgeBetweennessVector;
}

std::vector< double > mitk::ConnectomicsNetwork::GetShortestDistanceVectorFromLabel( std::string targetLabel ) const
{
  std::vector< VertexDescriptorType > predecessorMap( boost::num_vertices( m_Network ) );
  int numberOfNodes( boost::num_vertices( m_Network ) );

  std::vector< double > distanceMatrix;
  distanceMatrix.resize( numberOfNodes );

  boost::graph_traits<NetworkType>::vertex_iterator iterator, end;
  boost::tie(iterator, end) = boost::vertices( m_Network );

  while( (iterator != end) && (m_Network[ *iterator ].label != targetLabel) )
  {
    ++iterator;
  }

  if( iterator == end )
  {
    MITK_WARN << "Label not found";
    return distanceMatrix;
  }

  boost::dijkstra_shortest_paths(m_Network, *iterator, boost::predecessor_map(&predecessorMap[ 0 ]).distance_map(&distanceMatrix[ 0 ]).weight_map( boost::get( &NetworkEdge::edge_weight ,m_Network ) ) ) ;

  return distanceMatrix;
}

bool mitk::ConnectomicsNetwork::CheckForLabel( std::string targetLabel ) const
{
  boost::graph_traits<NetworkType>::vertex_iterator iterator, end;
  boost::tie(iterator, end) = boost::vertices( m_Network );

  while( (iterator != end) && (m_Network[ *iterator ].label != targetLabel) )
  {
    ++iterator;
  }

  if( iterator == end )
  {
    return false;
  }

  return true;
}

bool mitk::Equal( mitk::ConnectomicsNetwork* leftHandSide, mitk::ConnectomicsNetwork* rightHandSide, mitk::ScalarType eps, bool verbose )
{
  bool noDifferenceFound = true;

    if( rightHandSide == NULL )
  {
    if(verbose)
    {
      MITK_INFO << "[Equal( ConnectomicsNetwork*, ConnectomicsNetwork* )] rightHandSide NULL.";
    }
    return false;
  }

  if( leftHandSide == NULL )
  {
    if(verbose)
    {
      MITK_INFO << "[Equal( ConnectomicsNetwork*, ConnectomicsNetwork* )] leftHandSide NULL.";
    }
    return false;
  }

  mitk::ConnectomicsStatisticsCalculator::Pointer calculatorLeft = mitk::ConnectomicsStatisticsCalculator::New();
    mitk::ConnectomicsStatisticsCalculator::Pointer calculatorRight = mitk::ConnectomicsStatisticsCalculator::New();

    calculatorLeft->SetNetwork( leftHandSide );
    calculatorRight->SetNetwork( rightHandSide );
    calculatorLeft->Update();
    calculatorRight->Update();

    if( ! mitk::Equal( calculatorLeft->GetNumberOfVertices(), calculatorRight->GetNumberOfVertices(), eps ) )
    {
      if(verbose)
        MITK_INFO << "[Equal( ConnectomicsNetwork*, ConnectomicsNetwork* )] Number of vertices not equal. " << calculatorLeft->GetNumberOfVertices() << " vs " << calculatorRight->GetNumberOfVertices();
      noDifferenceFound = false;
    }

    if( ! mitk::Equal( calculatorLeft->GetNumberOfEdges(), calculatorRight->GetNumberOfEdges(), eps ) )
    {
      if(verbose)
        MITK_INFO << "[Equal( ConnectomicsNetwork*, ConnectomicsNetwork* )] Number of edges not equal. " << calculatorLeft->GetNumberOfEdges() << " vs " << calculatorRight->GetNumberOfEdges();
      noDifferenceFound = false;
    }

    if( ! mitk::Equal( calculatorLeft->GetSmallWorldness(), calculatorRight->GetSmallWorldness(), eps ) )
    {
      if(verbose)
        MITK_INFO << "[Equal( ConnectomicsNetwork*, ConnectomicsNetwork* )] Small worldness not equal. " << calculatorLeft->GetSmallWorldness() << " vs " << calculatorRight->GetSmallWorldness();
      noDifferenceFound = false;
    }

  return noDifferenceFound;
}

max_stars_repo_name: danielknorr/MITK

max_issues_repo_name: danielknorr/MITK

max_forks_repo_name: danielknorr/MITK


text:
//
//  parsing.hpp
//
//  Created by Anton Leuski on 9/30/11.
//  Copyright (c) 2015 Anton Leuski & ICT/USC. All rights reserved.
//
//  This file is part of Jerome.
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//

#ifndef __jerome_ir_parsing_hpp__
#define __jerome_ir_parsing_hpp__

#include <exception>
#include <list>
#include <boost/parameter.hpp>
#include <jerome/types.hpp>

#include <jerome/ir/parsing/token.hpp>
#include <jerome/ir/collection.hpp>
#include <jerome/ir/parsing/filters.hpp>

#ifdef JEROME_IOS
#	include <jerome/ir/parsing/parsing_cf.hpp>
#elif defined(JEROME_ANDROID)
#warning "Fix locale and Unicodde support!"
// Android NDK doesn't support cf, and boost locale is a pain to built.
// Thus we skip the whole boost local and create another parsing_std parser that uses only standatd C++.
// This parser only works for simple token parsing and does not support different locale or Unicode.
#   include <jerome/ir/parsing/parsing_std.hpp>
#else
#	include <jerome/ir/parsing/parsing_icu.hpp>
#endif

#include <jerome/ir/parsing/parsing_pipes.hpp>

#endif // defined __jerome_ir_parsing_hpp__

max_stars_repo_name: leuski-ict/jerome

max_issues_repo_name: leuski-ict/jerome

max_forks_repo_name: leuski-ict/jerome


text:
/*
 * This file belongs to the Galois project, a C++ library for exploiting
 * parallelism. The code is being released under the terms of the 3-Clause BSD
 * License (a copy is located in LICENSE.txt at the top-level directory).
 *
 * Copyright (C) 2018, The University of Texas at Austin. All rights reserved.
 * UNIVERSITY EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES CONCERNING THIS
 * SOFTWARE AND DOCUMENTATION, INCLUDING ANY WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR ANY PARTICULAR PURPOSE, NON-INFRINGEMENT AND WARRANTIES OF
 * PERFORMANCE, AND ANY WARRANTY THAT MIGHT OTHERWISE ARISE FROM COURSE OF
 * DEALING OR USAGE OF TRADE.  NO WARRANTY IS EITHER EXPRESS OR IMPLIED WITH
 * RESPECT TO THE USE OF THE SOFTWARE OR DOCUMENTATION. Under no circumstances
 * shall University be liable for incidental, special, indirect, direct or
 * consequential damages or loss of profits, interruption of business, or
 * related expenses which may arise from use of Software or Documentation,
 * including but not limited to those resulting from defects in Software and/or
 * Documentation, or loss or inaccuracy of data of any kind.
 */

#include "galois/Galois.h"
#include "galois/Reduction.h"
#include "galois/Timer.h"
#include "Lonestar/BoilerPlate.h"
#include "llvm/Support/CommandLine.h"

#include <boost/iterator/counting_iterator.hpp>

#include <chrono>
#include <cmath>
#include <iostream>
#include <vector>

typedef galois::GAccumulator<double> AccumDouble;

namespace cll = llvm::cl;

static cll::opt<int> size("size", cll::desc("length of vectors"),
                          cll::init(1000));
static cll::opt<int> rounds("rounds", cll::desc("number of rounds"),
                            cll::init(10000));
static cll::opt<int> trials("trials", cll::desc("number of trials"),
                            cll::init(1));
static cll::opt<unsigned> threads("threads", cll::desc("number of threads"),
                                  cll::init(2));

void runDoAllBurn(int num) {
  galois::substrate::getThreadPool().burnPower(galois::getActiveThreads());

  for (int r = 0; r < rounds; ++r) {
    galois::do_all(galois::iterate(0, num), [&](int) {
      asm volatile("" ::: "memory");
    });
  }

  galois::substrate::getThreadPool().beKind();
}

void runDoAll(int num) {
  for (int r = 0; r < rounds; ++r) {
    galois::do_all(galois::iterate(0, num), [&](int) {
      asm volatile("" ::: "memory");
    });
  }
}

void runExplicitThread(int num) {
  galois::substrate::Barrier& barrier =
      galois::runtime::getBarrier(galois::getActiveThreads());

  galois::on_each([&](unsigned tid, unsigned total) {
    auto range =
        galois::block_range(boost::counting_iterator<int>(0),
                            boost::counting_iterator<int>(num), tid, total);
    for (int r = 0; r < rounds; ++r) {
      for (auto ii = range.first, ei = range.second; ii != ei; ++ii) {
        asm volatile("" ::: "memory");
      }
      barrier();
    }
  });
}

void run(std::function<void(int)> fn, std::string name) {
  galois::Timer t;
  t.start();
  fn(size);
  t.stop();
  std::cout << name << " time: " << t.get() << "\n";
}

std::atomic<int> EXIT;

int main(int argc, char* argv[]) {
  galois::SharedMemSys Galois_runtime;
  LonestarStart(argc, argv, 0, 0, 0);

  galois::setActiveThreads(threads);

  EXIT                        = 0;
  std::function<void(void)> f = []() {
    while (!EXIT) {
      std::cerr << ".";
      std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
  };
  galois::substrate::getThreadPool().runDedicated(f);

  for (int t = 0; t < trials; ++t) {
    run(runDoAll, "DoAll");
    run(runDoAllBurn, "DoAllBurn");
    run(runExplicitThread, "ExplicitThread");
  }
  EXIT = 1;

  std::cout << "threads: " << galois::getActiveThreads() << " usable threads: "
            << galois::substrate::getThreadPool().getMaxUsableThreads()
            << " rounds: " << rounds << " size: " << size << "\n";

  return 0;
}

max_stars_repo_name: lineagech/Galois

max_issues_repo_name: lineagech/Galois

max_forks_repo_name: lineagech/Galois


text:
// Copyright (c) 2016 The Bitcoin Unlimited developers
// Copyright (c) 2016 Tom Zander <tomz@freedommail.ch>
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "thinblock.h"
#include <sstream>
#include <iomanip>

#include "main.h"
#include "chainparams.h"
#include "txmempool.h"

#include <consensus/validation.h>
#include <boost/foreach.hpp>
#include <boost/thread.hpp>

std::map<uint256, uint64_t> mapThinBlockTimer;

CXThinBlock::CXThinBlock(const CBlock& block, CBloomFilter* filter)
{
    header = block.GetBlockHeader();
    this->collision = false;

    unsigned int nTx = block.vtx.size();
    vTxHashes.reserve(nTx);
    std::set<uint64_t> setPartialTxHash;
    for (unsigned int i = 0; i < nTx; i++)
    {
        const uint256 hash256 = block.vtx[i].GetHash();
        uint64_t cheapHash = hash256.GetCheapHash();
        vTxHashes.push_back(cheapHash);

        if (setPartialTxHash.count(cheapHash))
                this->collision = true;
        setPartialTxHash.insert(cheapHash);

        // Find the transactions that do not match the filter.
        // These are the ones we need to relay back to the requesting peer.
        // NOTE: We always add the first tx, the coinbase as it is the one
        //       most often missing.
        if ((filter && !filter->contains(hash256)) || i == 0)
            vMissingTx.push_back(block.vtx[i]);
    }
}

CXThinBlock::CXThinBlock(const CBlock& block)
{
    header = block.GetBlockHeader();
    this->collision = false;

    unsigned int nTx = block.vtx.size();
    vTxHashes.reserve(nTx);
    std::set<uint64_t> setPartialTxHash;

    for (unsigned int i = 1; i < nTx; i++)
    {
        const uint256 hash256 = block.vtx[i].GetHash();
        uint64_t cheapHash = hash256.GetCheapHash();
        vTxHashes.push_back(cheapHash);

        if (setPartialTxHash.count(cheapHash))
                this->collision = true;
        setPartialTxHash.insert(cheapHash);

        // We always add the first tx, the coinbase as it is the one
        // most often missing.
        if (i == 0) vMissingTx.push_back(block.vtx[i]);
    }
}

CXThinBlockTx::CXThinBlockTx(uint256 blockHash, std::vector<CTransaction>& vTx)
{
    blockhash = blockHash;
    vMissingTx = vTx;
}

CXRequestThinBlockTx::CXRequestThinBlockTx(uint256 blockHash, std::set<uint64_t>& setHashesToRequest)
{
    blockhash = blockHash;
    setCheapHashesToRequest = setHashesToRequest;
}

bool HaveThinblockNodes()
{
    LOCK(cs_vNodes);
    BOOST_FOREACH (CNode* pnode, vNodes) {
        if (pnode->ThinBlockCapable())
            return true;
    }
    return false;
}

bool CheckThinblockTimer(const uint256 &hash)
{
    if (!mapThinBlockTimer.count(hash)) {
        mapThinBlockTimer[hash] = GetTimeMillis();
        LogPrint("thin", "Starting Preferential Thinblock timer\n");
    }
    else {
        // Check that we have not exceeded the 10 second limit.
        // If we have then we want to return false so that we can
        // proceed to download a regular block instead.
        uint64_t elapsed = GetTimeMillis() - mapThinBlockTimer[hash];
        if (elapsed > 10000) {
            LogPrint("thin", "Preferential Thinblock timer exceeded - downloading regular block instead\n");
            return false;
        }
    }
    return true;
}

bool IsChainNearlySyncd()
{
    LOCK(cs_main);
    if(chainActive.Height() < pindexBestHeader->nHeight - 2)
        return false;
    return true;
}

CBloomFilter createSeededBloomFilter(const std::vector<uint256>& vOrphanHashes)
{
    LogPrint("thin", "Starting creation of bloom filter\n");
    seed_insecure_rand();
    double nBloomPoolSize = (double)mempool.mapTx.size();
    if (nBloomPoolSize > MAX_BLOOM_FILTER_SIZE / 1.8)
        nBloomPoolSize = MAX_BLOOM_FILTER_SIZE / 1.8;
    double nBloomDecay = 1.5 - (nBloomPoolSize * 1.8 / MAX_BLOOM_FILTER_SIZE);  // We should never go below 0.5 as we will start seeing re-requests for tx's
    int nElements = std::max((int)(((int)mempool.mapTx.size() + (int)vOrphanHashes.size()) * nBloomDecay), 1); // Must make sure nElements is greater than zero or will assert
    double nFPRate = .001 + (((double)nElements * 1.8 / MAX_BLOOM_FILTER_SIZE) * .004); // The false positive rate in percent decays as the mempool grows
    CBloomFilter filterMemPool(nElements, nFPRate, insecure_rand(), BLOOM_UPDATE_ALL);
    LogPrint("thin", "Bloom multiplier: %f FPrate: %f Num elements in bloom filter: %d num mempool entries: %d\n", nBloomDecay, nFPRate, nElements, (int)mempool.mapTx.size());

    // Seed the filter with the transactions in the memory pool
    LOCK(cs_main);
    std::vector<uint256> vMemPoolHashes;
    mempool.queryHashes(vMemPoolHashes);
    for (uint64_t i = 0; i < vMemPoolHashes.size(); i++)
         filterMemPool.insert(vMemPoolHashes[i]);
    for (uint64_t i = 0; i < vOrphanHashes.size(); i++)
         filterMemPool.insert(vOrphanHashes[i]);
    LogPrint("thin", "Created bloom filter: %d bytes\n",::GetSerializeSize(filterMemPool, SER_NETWORK, PROTOCOL_VERSION));

    return filterMemPool;
}

void LoadFilter(CNode *pfrom, CBloomFilter *filter)
{
    if (!filter->IsWithinSizeConstraints())
        // There is no excuse for sending a too-large filter
        Misbehaving(pfrom->GetId(), 100);
    else
    {
        LOCK(pfrom->cs_filter);
        delete pfrom->pThinBlockFilter;
        pfrom->pThinBlockFilter = new CBloomFilter(*filter);
        pfrom->pThinBlockFilter->UpdateEmptyFull();
    }
    uint64_t nSizeFilter = ::GetSerializeSize(*pfrom->pThinBlockFilter, SER_NETWORK, PROTOCOL_VERSION);
    LogPrint("thin", "Thinblock Bloom filter size: %d\n", nSizeFilter);
}

void HandleBlockMessage(CNode *pfrom, const std::string &strCommand, const CBlock &block, const CInv &inv)
{
    int64_t startTime = GetTimeMicros();
    CValidationState state;
    // Process all blocks from whitelisted peers, even if not requested,
    // unless we're still syncing with the network.
    // Such an unrequested block may still be processed, subject to the
    // conditions in AcceptBlock().
    bool forceProcessing = pfrom->fWhitelisted && !IsInitialBlockDownload();
    const CChainParams& chainparams = Params();
    ProcessNewBlock(state, chainparams, pfrom, &block, forceProcessing, NULL);
    int nDoS;
    if (state.IsInvalid(nDoS)) {
        LogPrintf("Invalid block due to %s\n", state.GetRejectReason().c_str());
        pfrom->PushMessage("reject", strCommand, (unsigned char)state.GetRejectCode(),
                           state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), inv.hash);
        if (nDoS > 0) {
            LOCK(cs_main);
            Misbehaving(pfrom->GetId(), nDoS);
        }
    }
    LogPrint("thin", "Processed Block %s in %.2f seconds\n", inv.hash.ToString(), (double)(GetTimeMicros() - startTime) / 1000000.0);

    // When we request a thinblock we may get back a regular block if it is smaller than a thinblock
    // Therefore we have to remove the thinblock in flight if it exists and we also need to check that
    // the block didn't arrive from some other peer.  This code ALSO cleans up the thin block that
    // was passed to us (&block), so do not use it after this.
    {
        int nTotalThinBlocksInFlight = 0;
        LOCK(cs_vNodes);
        BOOST_FOREACH(CNode* pnode, vNodes) {
            if (pnode->mapThinBlocksInFlight.count(inv.hash)) {
                pnode->mapThinBlocksInFlight.erase(inv.hash);
                pnode->thinBlockWaitingForTxns = -1;
                pnode->thinBlock.SetNull();
            }
            if (pnode->mapThinBlocksInFlight.size() > 0)
                nTotalThinBlocksInFlight++;
        }

        // When we no longer have any thinblocks in flight then clear the set
        // just to make sure we don't somehow get growth over time.
        if (nTotalThinBlocksInFlight == 0) {
            setPreVerifiedTxHash.clear();
            setUnVerifiedOrphanTxHash.clear();
        }
    }

    // Clear the thinblock timer used for preferential download
    mapThinBlockTimer.erase(inv.hash);
}

max_stars_repo_name: infertux/bitcoinclassic

max_issues_repo_name: infertux/bitcoinclassic

max_forks_repo_name: infertux/bitcoinclassic


text:
#include <map>
#include <sstream>

#include <boost/algorithm/string.hpp>
#include <boost/filesystem/fstream.hpp>
#include <glm/gtc/matrix_transform.hpp>

#include "scene.hpp"

namespace hw4 {
    class SceneLoader {
        Scene* m_scene;
        std::istream* m_stream;
        boost::filesystem::path m_dir;

        std::map<std::string, std::shared_ptr<TriMesh>> m_models;
        std::map<std::string, std::shared_ptr<Material>> m_materials;

        size_t m_current_line_number = 0;
        std::vector<std::string> m_current_line;
        size_t m_current_indent;

        bool read_next_line();
        std::runtime_error syntax_error(std::function<void (std::ostream&)> fn);
        boost::filesystem::path resolve_path(std::string path);

        glm::vec3 read_vec3(size_t offset);

        glm::vec3 parse_vec3_attr(const std::string& name);
        float parse_float_attr(const std::string& name);
        std::string parse_string_attr(const std::string& name);
        boost::filesystem::path parse_path_attr(const std::string& name);

        void parse_mdl();
        void parse_mtl();
        void parse_plight();
        void parse_obj_mesh();
        void parse_obj_sphere();
        void parse_camera();
    public:
        SceneLoader(
            Scene* scene,
            std::istream* stream,
            boost::filesystem::path dir
        ) : m_scene(scene), m_stream(stream), m_dir(dir) {}

        void load();
    };

    static size_t count_indentation(const std::string& line) {
        size_t indentation = 0;

        for (char c : line) {
            if (c == ' ') {
                indentation += 1;
            } else if (c == '\t') {
                indentation += 4;
            } else {
                break;
            }
        }

        return indentation;
    }

    bool SceneLoader::read_next_line() {
        std::string line;

        while (std::getline(*this->m_stream, line)) {
            size_t comment_pos = line.find("#");

            if (comment_pos != std::string::npos) {
                line = line.substr(0, comment_pos);
            }

            size_t indent = count_indentation(line);
            boost::trim(line);

            this->m_current_line_number++;

            if (line.size() > 0) {
                this->m_current_line.clear();
                boost::split(
                    this->m_current_line,
                    line,
                    boost::is_any_of(" \t"),
                    boost::token_compress_on
                );

                this->m_current_indent = indent;
                return true;
            }
        }

        this->m_current_line.clear();
        this->m_current_indent = 0;
        return false;
    }

    std::runtime_error SceneLoader::syntax_error(std::function<void (std::ostream&)> fn) {
        std::ostringstream ss;

        ss << "Syntax error on line " << this->m_current_line_number << ": ";
        fn(ss);

        return std::runtime_error(ss.str());
    }

    boost::filesystem::path SceneLoader::resolve_path(std::string path) {
        boost::filesystem::path p(path);

        if (p.is_absolute()) {
            return p;
        } else {
            return this->m_dir / p;
        }
    }

    glm::vec3 SceneLoader::read_vec3(size_t offset) {
        assert(this->m_current_line.size() >= offset + 2);

        return glm::vec3(
            std::stof(this->m_current_line[offset]),
            std::stof(this->m_current_line[offset + 1]),
            std::stof(this->m_current_line[offset + 2])
        );
    }

    glm::vec3 SceneLoader::parse_vec3_attr(const std::string& name) {
        if (this->m_current_line.size() != 4) {
            throw this->syntax_error([&](auto& ss) {
                ss << "Wrong number of arguments for " << name << " attribute";
            });
        }

        try {
            return this->read_vec3(1);
        } catch (std::exception& e) {
            throw this->syntax_error([&](auto& ss) {
                ss << "Invalid arguments for " << name << " attribute";
            });
        }
    }

    float SceneLoader::parse_float_attr(const std::string& name) {
        if (this->m_current_line.size() != 2) {
            throw this->syntax_error([&](auto& ss) {
                ss << "Wrong number of arguments for " << name << " attribute";
            });
        }

        try {
            return std::stof(this->m_current_line[1]);
        } catch (std::exception& e) {
            throw this->syntax_error([&](auto& ss) {
                ss << "Invalid arguments for " << name << " attribute";
            });
        }
    }

    std::string SceneLoader::parse_string_attr(const std::string& name) {
        if (this->m_current_line.size() != 2) {
            throw this->syntax_error([&](auto& ss) {
                ss << "Wrong number of arguments for " << name << " attribute";
            });
        }

        return this->m_current_line[1];
    }

    boost::filesystem::path SceneLoader::parse_path_attr(const std::string& name) {
        return this->resolve_path(this->parse_string_attr(name));
    }

    void SceneLoader::parse_mdl() {
        if (this->m_current_line.size() != 3) {
            throw this->syntax_error([&](auto& ss) {
                ss << "Wrong number of arguments for mdl command";
            });
        }

        if (this->m_models.find(this->m_current_line[1]) != this->m_models.end()) {
            throw this->syntax_error([&](auto& ss) {
                ss << "A model \"" << this->m_current_line[1] << "\" already exists";
            });
        }

        this->m_models[this->m_current_line[1]] = TriMesh::load_mesh(
            this->resolve_path(this->m_current_line[2])
        );

        this->read_next_line();
    }

    void SceneLoader::parse_mtl() {
        if (this->m_current_line.size() != 2) {
            throw this->syntax_error([&](auto& ss) {
                ss << "Wrong number of arguments for mtl command";
            });
        }

        if (this->m_materials.find(this->m_current_line[1]) != this->m_materials.end()) {
            throw this->syntax_error([&](auto& ss) {
                ss << "A material \"" << this->m_current_line[1] << "\" already exists";
            });
        }

        auto name = this->m_current_line[1];
        size_t indent = this->m_current_indent;

        auto ambient = glm::vec3(1);
        auto diffuse = glm::vec3(1);
        auto specular = glm::vec3(1);
        float shininess = 1;

        std::shared_ptr<Texture2D> diffuse_texture;
        std::shared_ptr<Texture2D> ao_texture;

        float opacity = 1;

        float reflectance = 0;
        float transmittance = 0;
        float refractive_index = 1;

        if (this->read_next_line() && this->m_current_indent > indent) {
            indent = this->m_current_indent;

            do {
                const auto& cmd = this->m_current_line[0];

                if (cmd == "ambient") {
                    ambient = this->parse_vec3_attr("mtl::ambient");
                } else if (cmd == "diffuse") {
                    diffuse = this->parse_vec3_attr("mtl::diffuse");
                } else if (cmd == "specular") {
                    specular = this->parse_vec3_attr("mtl::specular");
                } else if (cmd == "shininess") {
                    shininess = this->parse_float_attr("mtl::shininess");
                } else if (cmd == "opacity") {
                    opacity = this->parse_float_attr("mtl::opacity");
                } else if (cmd == "reflectance") {
                    reflectance = this->parse_float_attr("mtl::reflectance");
                } else if (cmd == "transmittance") {
                    transmittance = this->parse_float_attr("mtl::transmittance");
                } else if (cmd == "refractive_index") {
                    refractive_index = this->parse_float_attr("mtl::refractive_index");
                } else if (cmd == "diffuse_map") {
                    diffuse_texture = Texture2D::load(this->parse_path_attr("mtl::diffuse_map").string());
                } else if (cmd == "ao_map") {
                    ao_texture = Texture2D::load(this->parse_path_attr("mtl::ao_map").string());
                } else {
                    throw this->syntax_error([&](auto& ss) {
                        ss << "Invalid mtl attribute \"" << cmd << "\"";
                    });
                }
            } while(this->read_next_line() && this->m_current_indent == indent);
        }

        this->m_materials[name] = std::make_shared<Material>(
            Material::textured(
                Material::translucent(
                    Material::reflective(
                        Material::diffuse(ambient, diffuse, specular, shininess),
                        reflectance
                    ),
                    opacity,
                    transmittance,
                    refractive_index
                ),
                diffuse_texture,
                ao_texture
            )
        );
    }

    void SceneLoader::parse_plight() {
        if (this->m_current_line.size() != 1) {
            throw this->syntax_error([&](auto& ss) {
                ss << "Wrong number of arguments for plight command";
            });
        }

        size_t indent = this->m_current_indent;

        auto pos = glm::vec3(0);
        auto ambient = glm::vec3(0);
        auto diffuse = glm::vec3(0);
        auto specular = glm::vec3(0);
        auto attenuation = glm::vec3(0);

        if (this->read_next_line() && this->m_current_indent > indent) {
            indent = this->m_current_indent;

            do {
                const auto& cmd = this->m_current_line[0];

                if (cmd == "pos") {
                    pos = this->parse_vec3_attr("plight::pos");
                } else if (cmd == "ambient") {
                    ambient = this->parse_vec3_attr("plight::ambient");
                } else if (cmd == "diffuse") {
                    diffuse = this->parse_vec3_attr("plight::diffuse");
                } else if (cmd == "specular") {
                    specular = this->parse_vec3_attr("plight::specular");
                } else if (cmd == "atten") {
                    attenuation = this->parse_vec3_attr("plight::atten");
                } else {
                    throw this->syntax_error([&](auto& ss) {
                        ss << "Invalid plight attribute \"" << cmd << "\"";
                    });
                }
            } while (this->read_next_line() && this->m_current_indent == indent);
        }

        this->m_scene->point_lights().push_back(std::make_unique<PointLight>(
            pos,
            ambient,
            diffuse,
            specular,
            attenuation
        ));
    }

    void SceneLoader::parse_obj_mesh() {
        size_t indent = this->m_current_indent;

        std::shared_ptr<TriMesh> mdl;
        std::shared_ptr<Material> mtl;

        glm::vec3 pos;
        glm::vec3 rot;
        float scale = 1.0f;

        if (this->read_next_line() && this->m_current_indent > indent) {
            indent = this->m_current_indent;

            do {
                const auto& cmd = this->m_current_line[0];

                if (cmd == "mdl") {
                    auto mdl_name = this->parse_string_attr("obj::mdl");
                    auto mdl_it = this->m_models.find(mdl_name);

                    if (mdl_it == this->m_models.end()) {
                        throw this->syntax_error([&](auto& ss) {
                            ss << "No such model: " << this->m_current_line[1];
                        });
                    }

                    mdl = mdl_it->second;
                } else if (cmd == "mtl") {
                    auto mtl_name = this->parse_string_attr("obj::mtl");
                    auto mtl_it = this->m_materials.find(this->m_current_line[1]);

                    if (mtl_it == this->m_materials.end()) {
                        throw this->syntax_error([&](auto& ss) {
                            ss << "No such material: " << this->m_current_line[1];
                        });
                    }

                    mtl = mtl_it->second;
                } else if (cmd == "pos") {
                    pos = this->parse_vec3_attr("pos");
                } else if (cmd == "rot") {
                    rot = this->parse_vec3_attr("rot");
                } else if (cmd == "scale") {
                    scale = this->parse_float_attr("obj::scale");
                } else {
                    throw this->syntax_error([&](auto& ss) {
                        ss << "Invalid obj attribute \"" << cmd << "\"";
                    });
                }
            } while (this->read_next_line() && this->m_current_indent == indent);
        }

        if (!mtl) {
            throw this->syntax_error([&](auto& ss) {
                ss << "Attribute obj::mtl is required";
            });
        } else if (!mdl) {
            throw this->syntax_error([&](auto& ss) {
                ss << "Attribute obj::mdl is required for mesh objects";
            });
        }

        this->m_scene->objects().push_back(std::make_unique<TriMeshObject>(
            mdl,
            apply_orientation(
                glm::scale(
                    glm::translate(glm::mat4(), pos),
                    glm::vec3(scale)
                ),
                rot
            ),
            mtl
        ));
    }

    void SceneLoader::parse_obj_sphere() {
        size_t indent = this->m_current_indent;

        std::shared_ptr<Material> mtl;

        glm::vec3 pos;
        float scale = 1.0f;

        if (this->read_next_line() && this->m_current_indent > indent) {
            indent = this->m_current_indent;

            do {
                const auto& cmd = this->m_current_line[0];

                if (cmd == "mtl") {
                    auto mtl_name = this->parse_string_attr("obj::mtl");
                    auto mtl_it = this->m_materials.find(this->m_current_line[1]);

                    if (mtl_it == this->m_materials.end()) {
                        throw this->syntax_error([&](auto& ss) {
                            ss << "No such material: " << this->m_current_line[1];
                        });
                    }

                    mtl = mtl_it->second;
                } else if (cmd == "pos") {
                    pos = this->parse_vec3_attr("obj::pos");
                } else if (cmd == "scale") {
                    scale = this->parse_float_attr("obj::scale");
                } else if (cmd == "mdl" || cmd == "rot") {
                    throw this->syntax_error([&](auto& ss) {
                        ss << "Attribute obj::" << cmd << " is not valid for sphere objects";
                    });
                } else {
                    throw this->syntax_error([&](auto& ss) {
                        ss << "Invalid obj attribute \"" << cmd << "\"";
                    });
                }
            } while (this->read_next_line() && this->m_current_indent == indent);
        }

        if (!mtl) {
            throw this->syntax_error([&](auto& ss) {
                ss << "Attribute obj::mtl is required";
            });
        }

        this->m_scene->objects().push_back(std::make_unique<SphereObject>(
            scale,
            pos,
            mtl
        ));
    }

    void SceneLoader::parse_camera() {
        if (this->m_current_line.size() != 2) {
            throw this->syntax_error([&](auto& ss) {
                ss << "Wrong number of arguments for cam command";
            });
        }

        if (this->m_scene->cameras().find(this->m_current_line[1]) != this->m_scene->cameras().end()) {
            throw this->syntax_error([&](auto& ss) {
                ss << "A camera \"" << this->m_current_line[1] << "\" already exists";
            });
        }

        auto name = this->m_current_line[1];
        size_t indent = this->m_current_indent;

        auto pos = glm::vec3(0, 0, 1);
        auto look_at = glm::vec3(0, 0, 0);
        auto up = glm::vec3(0, 1, 0);
        float hfov = 90.0f;

        if (this->read_next_line() && this->m_current_indent > indent) {
            indent = this->m_current_indent;

            do {
                const auto& cmd = this->m_current_line[0];

                if (cmd == "pos") {
                    pos = this->parse_vec3_attr("cam::pos");
                } else if (cmd == "lookat") {
                    look_at = this->parse_vec3_attr("cam::lookat");
                } else if (cmd == "up") {
                    up = this->parse_vec3_attr("cam::up");
                } else if (cmd == "hfov") {
                    hfov = this->parse_float_attr("cam::hfov");
                } else {
                    throw this->syntax_error([&](auto& ss) {
                        ss << "Invalid cam attribute \"" << cmd << "\"";
                    });
                }
            } while (this->read_next_line() && this->m_current_indent == indent);
        }

        this->m_scene->cameras().emplace(name, Camera(pos, look_at, up, glm::radians(hfov)));
    }

    void SceneLoader::load() {
        if (!this->read_next_line()) {
            return;
        }

        while (this->m_current_line.size() > 0) {
            const auto& cmd = this->m_current_line[0];

            if (this->m_current_indent != 0) {
                throw this->syntax_error([&](auto& ss) {
                    ss << "Bad indentation";
                });
            }

            if (cmd == "mdl") {
                this->parse_mdl();
            } else if (cmd == "mtl") {
                this->parse_mtl();
            } else if (cmd == "plight") {
                this->parse_plight();
            } else if (cmd == "obj") {
                if (this->m_current_line.size() != 2) {
                    throw this->syntax_error([&](auto& ss) {
                        ss << "Wrong number of arguments for obj command";
                    });
                }

                auto type = this->m_current_line[1];

                if (type == "mesh") {
                    this->parse_obj_mesh();
                } else if (type == "sphere") {
                    this->parse_obj_sphere();
                } else {
                    throw this->syntax_error([&](auto& ss) {
                        ss << "Invalid object type \"" << type << "\"";
                    });
                }
            } else if (cmd == "cam") {
                this->parse_camera();
            } else {
                throw this->syntax_error([&](auto& ss) {
                    ss << "Invalid scene command \"" << cmd << "\"";
                });
            }
        }
    }

    Scene Scene::load_scene(boost::filesystem::path path) {
        boost::filesystem::ifstream f(path);

        if (!f) {
            throw std::runtime_error(([&]() {
                std::ostringstream ss;

                ss << "Failed to open object file \"" << path.string() << "\"";

                return ss.str();
            })());
        }

        Scene scene;
        SceneLoader loader(&scene, &f, path.parent_path());

        loader.load();

        if (f.bad()) {
            throw std::runtime_error(([&]() {
                std::ostringstream ss;

                ss << "Error reading scene file \"" << path.string() << "\"";

                return ss.str();
            })());
        }

        return scene;
    }
}

max_stars_repo_name: wasmjit-omr/raytracer

max_issues_repo_name: wasmjit-omr/raytracer

max_forks_repo_name: wasmjit-omr/raytracer


text: #include <boost/winapi/time.hpp>

max_stars_repo_name: miathedev/BoostForArduino

max_issues_repo_name: miathedev/BoostForArduino

max_forks_repo_name: miathedev/BoostForArduino


text:
#ifndef BOOST_ALL_DYN_LINK
#define BOOST_ALL_DYN_LINK
#endif

#include <stdexcept>
#include <boost/filesystem.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/algorithm/string.hpp>

#include "gnuplot-iostream.h"

#include "opencv2/core/utility.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"

#include "gk_utils.h"

using namespace std;
using namespace cv;
namespace fs=boost::filesystem;

namespace gekon {
    tr_sample_t load_img_pair(const std::string path, const std::string name) {

        tr_sample_t sample = tr_sample_t();

        cout << "Loading image pair "
        << path + name + org_suff + suff << " and "
        << path + name + mod_suff + suff << "... ";

        sample.original = imread(path + name + org_suff + suff, 1);
        if (sample.original.empty()) {
            cout << endl;
            throw runtime_error("Original image " + path + name + org_suff + suff + " is unreadable or not found.");
        }

        sample.modified = imread(path + name + mod_suff + suff, 1);
        if (sample.modified.empty()) {
            cout << endl;
            throw runtime_error("Modified image " + path + name + mod_suff + suff + " is unreadable or not found.");
        }

        cout << "Done." << endl;
        return sample;
    }

    std::vector <tr_sample_t> load_samples(const std::string dir_name) {
        vector <tr_sample_t> samples;
        fs::path directory(dir_name);
        if (!fs::is_directory(directory)) {
            cout << dir_name << " is not a directory!" << endl;
            assert(false);
        }

        for (auto &f : boost::make_iterator_range(fs::directory_iterator(directory), {})) {
            std::string filename = f.path().string();
            std::vector <std::string> strs;

            // split address by '.' and '/'
            boost::split(strs, filename, boost::is_any_of("./"));

            if (suff.compare("." + strs[strs.size() - 1]) == 0) {
                // suffix match, continue
                if (mod_suff.compare("." + strs[strs.size() - 2]) == 0) {
                    // modified suffix match, continue
                    std::string name = strs[strs.size() - 3];
                    std::string path = filename.substr(0,
                                                       filename.size() - suff.size() - mod_suff.size() - name.size());
                    try {
                        // we expect existence of original when modified version found.
                        samples.push_back(load_img_pair(path, name));
                    } catch (exception &e) {
                        // if not, never mind, just inform user.
                        cerr << "[ERROR] Matching original image not found. " << e.what() << endl;
                    }
                }
            }
        }

        return samples;
    }

    void plot_graph(const std::vector<double> points, std::string name) {
        Gnuplot gp;

        gp << "plot" << gp.file1d(points) << "with lines title '" << name << "'\n";
    }
}

max_stars_repo_name: argorain/GeKon

max_issues_repo_name: argorain/GeKon

max_forks_repo_name: argorain/GeKon