<commit_before>#include "IRVisitor.h"
#include "IR.h"

namespace Halide {
namespace Internal {

IRVisitor::~IRVisitor() {
}

void IRVisitor::visit(const IntImm *) {
}

void IRVisitor::visit(const FloatImm *) {
}

void IRVisitor::visit(const StringImm *) {
}

void IRVisitor::visit(const Cast *op) {
    op->value.accept(this);
}

void IRVisitor::visit(const Variable *) {
}

void IRVisitor::visit(const Add *op) {
    op->a.accept(this);
    op->b.accept(this);
}

void IRVisitor::visit(const Sub *op) {
    op->a.accept(this);
    op->b.accept(this);
}

void IRVisitor::visit(const Mul *op) {
    op->a.accept(this);
    op->b.accept(this);
}

void IRVisitor::visit(const Div *op) {
    op->a.accept(this);
    op->b.accept(this);
}

void IRVisitor::visit(const Mod *op) {
    op->a.accept(this);
    op->b.accept(this);
}

void IRVisitor::visit(const Min *op) {
    op->a.accept(this);
    op->b.accept(this);
}

void IRVisitor::visit(const Max *op) {
    op->a.accept(this);
    op->b.accept(this);
}

void IRVisitor::visit(const EQ *op) {
    op->a.accept(this);
    op->b.accept(this);
}

void IRVisitor::visit(const NE *op) {
    op->a.accept(this);
    op->b.accept(this);
}

void IRVisitor::visit(const LT *op) {
    op->a.accept(this);
    op->b.accept(this);
}

void IRVisitor::visit(const LE *op) {
    op->a.accept(this);
    op->b.accept(this);
}

void IRVisitor::visit(const GT *op) {
    op->a.accept(this);
    op->b.accept(this);
}

void IRVisitor::visit(const GE *op) {
    op->a.accept(this);
    op->b.accept(this);
}

void IRVisitor::visit(const And *op) {
    op->a.accept(this);
    op->b.accept(this);
}

void IRVisitor::visit(const Or *op) {
    op->a.accept(this);
    op->b.accept(this);
}

void IRVisitor::visit(const Not *op) {
    op->a.accept(this);
}

void IRVisitor::visit(const Select *op) {
    op->condition.accept(this);
    op->true_value.accept(this);
    op->false_value.accept(this);
}

void IRVisitor::visit(const Load *op) {
    op->index.accept(this);
}

void IRVisitor::visit(const Ramp *op) {
    op->base.accept(this);
    op->stride.accept(this);
}

void IRVisitor::visit(const Broadcast *op) {
    op->value.accept(this);
}

void IRVisitor::visit(const Call *op) {
    for (size_t i = 0; i < op->args.size(); i++) {
        op->args[i].accept(this);
    }
}

void IRVisitor::visit(const Let *op) {
    op->value.accept(this);
    op->body.accept(this);
}

void IRVisitor::visit(const LetStmt *op) {
    op->value.accept(this);
    op->body.accept(this);
}

void IRVisitor::visit(const AssertStmt *op) {
    op->condition.accept(this);
}

void IRVisitor::visit(const Pipeline *op) {
    op->produce.accept(this);
    if (op->update.defined()) op->update.accept(this);
    op->consume.accept(this);
}

void IRVisitor::visit(const For *op) {
    op->min.accept(this);
    op->extent.accept(this);
    op->body.accept(this);
}

void IRVisitor::visit(const Store *op) {
    op->value.accept(this);
    op->index.accept(this);
}

void IRVisitor::visit(const Provide *op) {
    for (size_t i = 0; i < op->values.size(); i++) {
        op->values[i].accept(this);
    }
    for (size_t i = 0; i < op->args.size(); i++) {
        op->args[i].accept(this);
    }
}

void IRVisitor::visit(const Allocate *op) {
    op->size.accept(this);
    op->body.accept(this);
}

void IRVisitor::visit(const Free *op) {
}

void IRVisitor::visit(const Realize *op) {
    for (size_t i = 0; i < op->bounds.size(); i++) {
        op->bounds[i].min.accept(this);
        op->bounds[i].extent.accept(this);
    }
    op->body.accept(this);
}

void IRVisitor::visit(const Block *op) {
    op->first.accept(this);
    if (op->rest.defined()) {
        op->rest.accept(this);
    }
}

void IRVisitor::visit(const IfThenElse *op) {
    op->condition.accept(this);
    op->then_case.accept(this);
    if (op->else_case.defined()) {
        op->else_case.accept(this);
    }
}

void IRVisitor::visit(const Evaluate *op) {
    op->value.accept(this);
}

void IRGraphVisitor::include(const Expr &e) {
    if (visited.count(e.ptr)) {
        return;
    } else {
        visited.insert(e.ptr);
        e.accept(this);
        return;
    }
}

void IRGraphVisitor::include(const Stmt &s) {
    if (visited.count(s.ptr)) {
        return;
    } else {
        visited.insert(s.ptr);
        s.accept(this);
        return;
    }
}

void IRGraphVisitor::visit(const IntImm *) {
}

void IRGraphVisitor::visit(const FloatImm *) {
}

void IRGraphVisitor::visit(const StringImm *) {
}

void IRGraphVisitor::visit(const Cast *op) {
    include(op->value);
}

void IRGraphVisitor::visit(const Variable *op) {
}

void IRGraphVisitor::visit(const Add *op) {
    include(op->a);
    include(op->b);
}

void IRGraphVisitor::visit(const Sub *op) {
    include(op->a);
    include(op->b);
}

void IRGraphVisitor::visit(const Mul *op) {
    include(op->a);
    include(op->b);
}

void IRGraphVisitor::visit(const Div *op) {
    include(op->a);
    include(op->b);
}

void IRGraphVisitor::visit(const Mod *op) {
    include(op->a);
    include(op->b);
}

void IRGraphVisitor::visit(const Min *op) {
    include(op->a);
    include(op->b);
}

void IRGraphVisitor::visit(const Max *op) {
    include(op->a);
    include(op->b);
}

void IRGraphVisitor::visit(const EQ *op) {
    include(op->a);
    include(op->b);
}

void IRGraphVisitor::visit(const NE *op) {
    include(op->a);
    include(op->b);
}

void IRGraphVisitor::visit(const LT *op) {
    include(op->a);
    include(op->b);
}

void IRGraphVisitor::visit(const LE *op) {
    include(op->a);
    include(op->b);
}

void IRGraphVisitor::visit(const GT *op) {
    include(op->a);
    include(op->b);
}

void IRGraphVisitor::visit(const GE *op) {
    include(op->a);
    include(op->b);
}

void IRGraphVisitor::visit(const And *op) {
    include(op->a);
    include(op->b);
}

void IRGraphVisitor::visit(const Or *op) {
    include(op->a);
    include(op->b);
}

void IRGraphVisitor::visit(const Not *op) {
    include(op->a);
}

void IRGraphVisitor::visit(const Select *op) {
    include(op->condition);
    include(op->true_value);
    include(op->false_value);
}

void IRGraphVisitor::visit(const Load *op) {
    include(op->index);
}

void IRGraphVisitor::visit(const Ramp *op) {
    include(op->base);
    include(op->stride);
}

void IRGraphVisitor::visit(const Broadcast *op) {
    include(op->value);
}

void IRGraphVisitor::visit(const Call *op) {
    for (size_t i = 0; i < op->args.size(); i++) {
        include(op->args[i]);
    }
}

void IRGraphVisitor::visit(const Let *op) {
    include(op->value);
    include(op->body);
}

void IRGraphVisitor::visit(const LetStmt *op) {
    include(op->value);
    include(op->body);
}

void IRGraphVisitor::visit(const AssertStmt *op) {
    include(op->condition);
}

void IRGraphVisitor::visit(const Pipeline *op) {
    include(op->produce);
    if (op->update.defined()) include(op->update);
    include(op->consume);
}

void IRGraphVisitor::visit(const For *op) {
    include(op->min);
    include(op->extent);
    include(op->body);
}

void IRGraphVisitor::visit(const Store *op) {
    include(op->value);
    include(op->index);
}

void IRGraphVisitor::visit(const Provide *op) {
    for (size_t i = 0; i < op->values.size(); i++) {
        include(op->values[i]);
    }
    for (size_t i = 0; i < op->args.size(); i++) {
        include(op->args[i]);
    }
}

void IRGraphVisitor::visit(const Allocate *op) {
    include(op->size);
    include(op->body);
}

void IRGraphVisitor::visit(const Free *op) {
}

void IRGraphVisitor::visit(const Realize *op) {
    for (size_t i = 0; i < op->bounds.size(); i++) {
        include(op->bounds[i].min);
        include(op->bounds[i].extent);
    }
    include(op->body);
}

void IRGraphVisitor::visit(const Block *op) {
    include(op->first);
    if (op->rest.defined()) include(op->rest);
}

void IRGraphVisitor::visit(const IfThenElse *op) {
    include(op->condition);
    include(op->then_case);
    if (op->else_case.defined()) {
        include(op->else_case);
    }
}

void IRGraphVisitor::visit(const Evaluate *op) {
    include(op->value);
}

void IRDeepVisitor::visit(const Call *call) {
    IRVisitor::visit(call);
    if (call->call_type == Call::Halide) {
        Function f = call->func;
        std::map<std::string, Function>::iterator iter = funcs.find(f.name());
        if (iter == funcs.end()) {
            funcs[f.name()] = f;
            visit_function(this, f);
        } else {
            assert(iter->second.same_as(f) &&
                   "Can't compile a pipeline using multiple functions with same name");
        }
    }
}

void visit_function(IRVisitor *v, const Function &f) {
    // recursively add everything called in the definition of f
    for (size_t i = 0; i < f.values().size(); i++) {
        f.values()[i].accept(v);
    }
    // recursively add everything called in the definition of f's update steps
    for (size_t i = 0; i < f.reductions().size(); i++) {
        // Update value definition
        for (size_t j = 0; j < f.reductions()[i].values.size(); j++) {
            f.reductions()[i].values[j].accept(v);
        }
        // Update index expressions
        for (size_t j = 0; j < f.reductions()[i].args.size(); j++) {
            f.reductions()[i].args[j].accept(v);
        }
        // Reduction domain min/extent expressions
        for (size_t j = 0; j < f.reductions()[i].domain.domain().size(); j++) {
            f.reductions()[i].domain.domain()[j].min.accept(v);
            f.reductions()[i].domain.domain()[j].extent.accept(v);
        }
    }
}

}
}

<commit_msg>Traverse Expr ExternArguments in IRVisitor<commit_after>#include "IRVisitor.h"
#include "IR.h"

namespace Halide {
namespace Internal {

IRVisitor::~IRVisitor() {
}

void IRVisitor::visit(const IntImm *) {
}

void IRVisitor::visit(const FloatImm *) {
}

void IRVisitor::visit(const StringImm *) {
}

void IRVisitor::visit(const Cast *op) {
    op->value.accept(this);
}

void IRVisitor::visit(const Variable *) {
}

void IRVisitor::visit(const Add *op) {
    op->a.accept(this);
    op->b.accept(this);
}

void IRVisitor::visit(const Sub *op) {
    op->a.accept(this);
    op->b.accept(this);
}

void IRVisitor::visit(const Mul *op) {
    op->a.accept(this);
    op->b.accept(this);
}

void IRVisitor::visit(const Div *op) {
    op->a.accept(this);
    op->b.accept(this);
}

void IRVisitor::visit(const Mod *op) {
    op->a.accept(this);
    op->b.accept(this);
}

void IRVisitor::visit(const Min *op) {
    op->a.accept(this);
    op->b.accept(this);
}

void IRVisitor::visit(const Max *op) {
    op->a.accept(this);
    op->b.accept(this);
}

void IRVisitor::visit(const EQ *op) {
    op->a.accept(this);
    op->b.accept(this);
}

void IRVisitor::visit(const NE *op) {
    op->a.accept(this);
    op->b.accept(this);
}

void IRVisitor::visit(const LT *op) {
    op->a.accept(this);
    op->b.accept(this);
}

void IRVisitor::visit(const LE *op) {
    op->a.accept(this);
    op->b.accept(this);
}

void IRVisitor::visit(const GT *op) {
    op->a.accept(this);
    op->b.accept(this);
}

void IRVisitor::visit(const GE *op) {
    op->a.accept(this);
    op->b.accept(this);
}

void IRVisitor::visit(const And *op) {
    op->a.accept(this);
    op->b.accept(this);
}

void IRVisitor::visit(const Or *op) {
    op->a.accept(this);
    op->b.accept(this);
}

void IRVisitor::visit(const Not *op) {
    op->a.accept(this);
}

void IRVisitor::visit(const Select *op) {
    op->condition.accept(this);
    op->true_value.accept(this);
    op->false_value.accept(this);
}

void IRVisitor::visit(const Load *op) {
    op->index.accept(this);
}

void IRVisitor::visit(const Ramp *op) {
    op->base.accept(this);
    op->stride.accept(this);
}

void IRVisitor::visit(const Broadcast *op) {
    op->value.accept(this);
}

void IRVisitor::visit(const Call *op) {
    for (size_t i = 0; i < op->args.size(); i++) {
        op->args[i].accept(this);
    }

    // Consider extern call args
    Function f = op->func;
    if (op->call_type == Call::Halide && f.has_extern_definition()) {
        for (size_t i = 0; i < f.extern_arguments().size(); i++) {
            ExternFuncArgument arg = f.extern_arguments()[i];
            if (arg.is_expr()) {
                arg.expr.accept(this);
            }
        }
    }
}

void IRVisitor::visit(const Let *op) {
    op->value.accept(this);
    op->body.accept(this);
}

void IRVisitor::visit(const LetStmt *op) {
    op->value.accept(this);
    op->body.accept(this);
}

void IRVisitor::visit(const AssertStmt *op) {
    op->condition.accept(this);
}

void IRVisitor::visit(const Pipeline *op) {
    op->produce.accept(this);
    if (op->update.defined()) op->update.accept(this);
    op->consume.accept(this);
}

void IRVisitor::visit(const For *op) {
    op->min.accept(this);
    op->extent.accept(this);
    op->body.accept(this);
}

void IRVisitor::visit(const Store *op) {
    op->value.accept(this);
    op->index.accept(this);
}

void IRVisitor::visit(const Provide *op) {
    for (size_t i = 0; i < op->values.size(); i++) {
        op->values[i].accept(this);
    }
    for (size_t i = 0; i < op->args.size(); i++) {
        op->args[i].accept(this);
    }
}

void IRVisitor::visit(const Allocate *op) {
    op->size.accept(this);
    op->body.accept(this);
}

void IRVisitor::visit(const Free *op) {
}

void IRVisitor::visit(const Realize *op) {
    for (size_t i = 0; i < op->bounds.size(); i++) {
        op->bounds[i].min.accept(this);
        op->bounds[i].extent.accept(this);
    }
    op->body.accept(this);
}

void IRVisitor::visit(const Block *op) {
    op->first.accept(this);
    if (op->rest.defined()) {
        op->rest.accept(this);
    }
}

void IRVisitor::visit(const IfThenElse *op) {
    op->condition.accept(this);
    op->then_case.accept(this);
    if (op->else_case.defined()) {
        op->else_case.accept(this);
    }
}

void IRVisitor::visit(const Evaluate *op) {
    op->value.accept(this);
}

void IRGraphVisitor::include(const Expr &e) {
    if (visited.count(e.ptr)) {
        return;
    } else {
        visited.insert(e.ptr);
        e.accept(this);
        return;
    }
}

void IRGraphVisitor::include(const Stmt &s) {
    if (visited.count(s.ptr)) {
        return;
    } else {
        visited.insert(s.ptr);
        s.accept(this);
        return;
    }
}

void IRGraphVisitor::visit(const IntImm *) {
}

void IRGraphVisitor::visit(const FloatImm *) {
}

void IRGraphVisitor::visit(const StringImm *) {
}

void IRGraphVisitor::visit(const Cast *op) {
    include(op->value);
}

void IRGraphVisitor::visit(const Variable *op) {
}

void IRGraphVisitor::visit(const Add *op) {
    include(op->a);
    include(op->b);
}

void IRGraphVisitor::visit(const Sub *op) {
    include(op->a);
    include(op->b);
}

void IRGraphVisitor::visit(const Mul *op) {
    include(op->a);
    include(op->b);
}

void IRGraphVisitor::visit(const Div *op) {
    include(op->a);
    include(op->b);
}

void IRGraphVisitor::visit(const Mod *op) {
    include(op->a);
    include(op->b);
}

void IRGraphVisitor::visit(const Min *op) {
    include(op->a);
    include(op->b);
}

void IRGraphVisitor::visit(const Max *op) {
    include(op->a);
    include(op->b);
}

void IRGraphVisitor::visit(const EQ *op) {
    include(op->a);
    include(op->b);
}

void IRGraphVisitor::visit(const NE *op) {
    include(op->a);
    include(op->b);
}

void IRGraphVisitor::visit(const LT *op) {
    include(op->a);
    include(op->b);
}

void IRGraphVisitor::visit(const LE *op) {
    include(op->a);
    include(op->b);
}

void IRGraphVisitor::visit(const GT *op) {
    include(op->a);
    include(op->b);
}

void IRGraphVisitor::visit(const GE *op) {
    include(op->a);
    include(op->b);
}

void IRGraphVisitor::visit(const And *op) {
    include(op->a);
    include(op->b);
}

void IRGraphVisitor::visit(const Or *op) {
    include(op->a);
    include(op->b);
}

void IRGraphVisitor::visit(const Not *op) {
    include(op->a);
}

void IRGraphVisitor::visit(const Select *op) {
    include(op->condition);
    include(op->true_value);
    include(op->false_value);
}

void IRGraphVisitor::visit(const Load *op) {
    include(op->index);
}

void IRGraphVisitor::visit(const Ramp *op) {
    include(op->base);
    include(op->stride);
}

void IRGraphVisitor::visit(const Broadcast *op) {
    include(op->value);
}

void IRGraphVisitor::visit(const Call *op) {
    for (size_t i = 0; i < op->args.size(); i++) {
        include(op->args[i]);
    }
}

void IRGraphVisitor::visit(const Let *op) {
    include(op->value);
    include(op->body);
}

void IRGraphVisitor::visit(const LetStmt *op) {
    include(op->value);
    include(op->body);
}

void IRGraphVisitor::visit(const AssertStmt *op) {
    include(op->condition);
}

void IRGraphVisitor::visit(const Pipeline *op) {
    include(op->produce);
    if (op->update.defined()) include(op->update);
    include(op->consume);
}

void IRGraphVisitor::visit(const For *op) {
    include(op->min);
    include(op->extent);
    include(op->body);
}

void IRGraphVisitor::visit(const Store *op) {
    include(op->value);
    include(op->index);
}

void IRGraphVisitor::visit(const Provide *op) {
    for (size_t i = 0; i < op->values.size(); i++) {
        include(op->values[i]);
    }
    for (size_t i = 0; i < op->args.size(); i++) {
        include(op->args[i]);
    }
}

void IRGraphVisitor::visit(const Allocate *op) {
    include(op->size);
    include(op->body);
}

void IRGraphVisitor::visit(const Free *op) {
}

void IRGraphVisitor::visit(const Realize *op) {
    for (size_t i = 0; i < op->bounds.size(); i++) {
        include(op->bounds[i].min);
        include(op->bounds[i].extent);
    }
    include(op->body);
}

void IRGraphVisitor::visit(const Block *op) {
    include(op->first);
    if (op->rest.defined()) include(op->rest);
}

void IRGraphVisitor::visit(const IfThenElse *op) {
    include(op->condition);
    include(op->then_case);
    if (op->else_case.defined()) {
        include(op->else_case);
    }
}

void IRGraphVisitor::visit(const Evaluate *op) {
    include(op->value);
}

void IRDeepVisitor::visit(const Call *call) {
    IRVisitor::visit(call);
    if (call->call_type == Call::Halide) {
        Function f = call->func;
        std::map<std::string, Function>::iterator iter = funcs.find(f.name());
        if (iter == funcs.end()) {
            funcs[f.name()] = f;
            visit_function(this, f);
        } else {
            assert(iter->second.same_as(f) &&
                   "Can't compile a pipeline using multiple functions with same name");
        }
    }
}

void visit_function(IRVisitor *v, const Function &f) {
    // recursively add everything called in the definition of f
    for (size_t i = 0; i < f.values().size(); i++) {
        f.values()[i].accept(v);
    }
    // recursively add everything called in the definition of f's update steps
    for (size_t i = 0; i < f.reductions().size(); i++) {
        // Update value definition
        for (size_t j = 0; j < f.reductions()[i].values.size(); j++) {
            f.reductions()[i].values[j].accept(v);
        }
        // Update index expressions
        for (size_t j = 0; j < f.reductions()[i].args.size(); j++) {
            f.reductions()[i].args[j].accept(v);
        }
        // Reduction domain min/extent expressions
        for (size_t j = 0; j < f.reductions()[i].domain.domain().size(); j++) {
            f.reductions()[i].domain.domain()[j].min.accept(v);
            f.reductions()[i].domain.domain()[j].extent.accept(v);
        }
    }
}

}
}

<|endoftext|>


<commit_before>#include "LeftAlign.h"

//bool debug;

// Attempts to left-realign all the indels represented by the alignment cigar.
//
// This is done by shifting all indels as far left as they can go without
// mismatch, then merging neighboring indels of the same class.  leftAlign
// updates the alignment cigar with changes, and returns true if realignment
// changed the alignment cigar.
//
// To left-align, we move multi-base indels left by their own length as long as
// the preceding bases match the inserted or deleted sequence.  After this
// step, we handle multi-base homopolymer indels by shifting them one base to
// the left until they mismatch the reference.
//
// To merge neighboring indels, we iterate through the set of left-stabilized
// indels.  For each indel we add a new cigar element to the new cigar.  If a
// deletion follows a deletion, or an insertion occurs at the same place as
// another insertion, we merge the events by extending the previous cigar
// element.
//
// In practice, we must call this function until the alignment is stabilized.
//
bool leftAlign(BamAlignment& alignment, string& referenceSequence, bool debug) {

    int arsOffset = 0; // pointer to insertion point in aligned reference sequence
    string alignedReferenceSequence = referenceSequence;
    int aabOffset = 0;
    string alignmentAlignedBases = alignment.QueryBases;

    // store information about the indels
    vector<IndelAllele> indels;

    int rp = 0;  // read position, 0-based relative to read
    int sp = 0;  // sequence position

    string softBegin;
    string softEnd;

    stringstream cigar_before, cigar_after;
    for (vector<CigarOp>::const_iterator c = alignment.CigarData.begin();
        c != alignment.CigarData.end(); ++c) {
        unsigned int l = c->Length;
        char t = c->Type;
        cigar_before << l << t;
        if (t == 'M') { // match or mismatch
            sp += l;
            rp += l;
        } else if (t == 'D') { // deletion
            indels.push_back(IndelAllele(false, l, sp, rp, referenceSequence.substr(sp, l)));
            alignmentAlignedBases.insert(rp + aabOffset, string(l, '-'));
            aabOffset += l;
            sp += l;  // update sample position
        } else if (t == 'I') { // insertion
            indels.push_back(IndelAllele(true, l, sp, rp, alignment.QueryBases.substr(rp, l)));
            alignedReferenceSequence.insert(sp + softBegin.size() + arsOffset, string(l, '-'));
            arsOffset += l;
            rp += l;
        } else if (t == 'S') { // soft clip, clipped sequence present in the read not matching the reference
            // remove these bases from the refseq and read seq, but don't modify the alignment sequence
            if (rp == 0) {
                alignedReferenceSequence = string(l, '*') + alignedReferenceSequence;
                softBegin = alignmentAlignedBases.substr(0, l);
            } else {
                alignedReferenceSequence = alignedReferenceSequence + string(l, '*');
                softEnd = alignmentAlignedBases.substr(alignmentAlignedBases.size() - l, l);
            }
            rp += l;
        } else if (t == 'H') { // hard clip on the read, clipped sequence is not present in the read
        } else if (t == 'N') { // skipped region in the reference not present in read, aka splice
            sp += l;
        }
    }

    int alignedLength = sp;

    DEBUG("| " << cigar_before.str() << endl
       << "| " << alignedReferenceSequence << endl
       << "| " << alignmentAlignedBases << endl);

    // if no indels, return the alignment
    if (indels.empty()) { return false; }

    // for each indel, from left to right
    //     while the indel sequence repeated to the left and we're not matched up with the left-previous indel
    //         move the indel left

    vector<IndelAllele>::iterator previous = indels.begin();
    for (vector<IndelAllele>::iterator id = indels.begin(); id != indels.end(); ++id) {
        IndelAllele& indel = *id;
        int steppos = indel.position - indel.length;
        int readsteppos = (indel.insertion ? indel.readPosition - indel.length : indel.readPosition) - 1;
        // repeated subunits, single base homopolymers
        while (steppos >= 0 && readsteppos >= 0
               && indel.sequence == referenceSequence.substr(steppos, indel.length)
               && indel.sequence == alignment.QueryBases.substr(readsteppos, indel.length)
               && (id == indels.begin()
                   || (previous->insertion && steppos >= previous->position)
                   || (!previous->insertion && steppos >= previous->position + previous->length))) {
            DEBUG("indel " << indel << " shifting " << indel.length << "bp left" << endl);
            indel.position -= indel.length;
            indel.readPosition -= indel.length;
            steppos = indel.position - indel.length;
            readsteppos = (indel.insertion ? indel.readPosition - indel.length : indel.readPosition) - 1;
        }
        // multi-base homopolymers
        if (indel.homopolymer()) {
            while (indel.position > 0
                   && indel.sequence == referenceSequence.substr(indel.position - 1, indel.length)
                   && indel.sequence == alignment.QueryBases.substr(indel.readPosition - 1, indel.length)
                   && (id == indels.begin() || indel.position >= previous->position + previous->length)) {
                DEBUG("indel " << indel << " shifting " << 1 << "bp left" << endl);
                indel.position -= 1;
                indel.readPosition -= 1;
            }
        }
        previous = id;
    }

    // unhandled:
    // attempt to shift in lengths below the tandem dup size
    // replaces above loop, but...
    // buggy code:
    /*
    vector<IndelAllele>::iterator previous = indels.begin();
    for (vector<IndelAllele>::iterator id = indels.begin(); id != indels.end(); ++id) {
        IndelAllele& indel = *id;
        int steppos = indel.position - indel.length;
        int step = indel.length;
        while (steppos >= 0 && step > 0) {
            step = indel.length;
            steppos = indel.position - step;
            while (step > 0) {
                DEBUG(step << endl);
                if (indel.sequence == referenceSequence.substr(steppos, indel.length)
                   && (id == indels.begin()
                       || (previous->insertion && steppos >= previous->position)
                       || (!previous->insertion && steppos >= previous->position + previous->length))) {

                    DEBUG("indel " << indel << " shifting " << indel.length << "bp left" << endl);
                    indel.position -= step;
                    steppos = indel.position;
                    break;
                } else {
                    --step;
                }
            }
        }
        // multi-base homopolymers
        previous = id;
    }
       */

    // bring together floating indels
    // from left to right
    // check if we could merge with the next indel
    // if so, adjust so that we will merge in the next step
    if (indels.size() > 1) {
        previous = indels.begin();
        for (vector<IndelAllele>::iterator id = (indels.begin() + 1); id != indels.end(); ++id) {
            IndelAllele& indel = *id;
            // could we shift right and merge with the previous indel?
            // if so, do it
            int prev_end = previous->insertion ? previous->position : previous->position + previous->length;
            if (previous->insertion == indel.insertion
                    && ((previous->insertion && previous->position < indel.position)
                        ||
                        (!previous->insertion && previous->position + previous->length < indel.position))) {
                if (previous->homopolymer()) {
                    string seq = referenceSequence.substr(prev_end, indel.position - prev_end);
                    if (previous->sequence.at(0) == seq.at(0) && homopolymer(seq)) {
                        DEBUG("moving " << *previous << " right to "
                                << (indel.insertion ? indel.position : indel.position - previous->length) << endl);
                        previous->position = indel.insertion ? indel.position : indel.position - previous->length;
                    }
                }
                else {
                    int pos = previous->position;
                    while (pos < (int) referenceSequence.length() &&
                            ((previous->insertion && pos + previous->length <= indel.position)
                            ||
                            (!previous->insertion && pos + previous->length < indel.position))
                            && previous->sequence
                                == referenceSequence.substr(pos + previous->length, previous->length)) {
                        pos += previous->length;
                    }
                    if (pos < previous->position &&
                        ((previous->insertion && pos + previous->length == indel.position)
                        ||
                        (!previous->insertion && pos == indel.position - previous->length))
                       ) {
                        DEBUG("right-merging tandem repeat: moving " << *previous << " right to " << pos << endl);
                        previous->position = pos;
                    }
                }
            }
        }
    }

    // for each indel
    //     if ( we're matched up to the previous insertion (or deletion)
    //          and it's also an insertion or deletion )
    //         merge the indels

    vector<CigarOp> newCigar;

    if (!softBegin.empty()) {
        newCigar.push_back(CigarOp('S', softBegin.size()));
    }

    vector<IndelAllele>::iterator id = indels.begin();
    IndelAllele last = *id++;
    if (last.position > 0) {
        newCigar.push_back(CigarOp('M', last.position));
        newCigar.push_back(CigarOp((last.insertion ? 'I' : 'D'), last.length));
    } else {
        newCigar.push_back(CigarOp((last.insertion ? 'I' : 'D'), last.length));
    }
    int lastend = last.insertion ? last.position : (last.position + last.length);
    DEBUG(last << ",");

    for (; id != indels.end(); ++id) {
        IndelAllele& indel = *id;
        DEBUG(indel << ",");
        if (indel.position < lastend) {
            cerr << "impossibility?: indel realigned left of another indel" << endl << alignment.Name
                << " " << alignment.Position << endl << alignment.QueryBases << endl;
            exit(1);
        } else if (indel.position == lastend && indel.insertion == last.insertion) {
            CigarOp& op = newCigar.back();
            op.Length += indel.length;
        } else if (indel.position > lastend) {
            newCigar.push_back(CigarOp('M', indel.position - lastend));
            newCigar.push_back(CigarOp((indel.insertion ? 'I' : 'D'), indel.length));
        }
        last = *id;
        lastend = last.insertion ? last.position : (last.position + last.length);
    }

    if ((last.position + last.length) < alignedLength) {
        newCigar.push_back(CigarOp('M', alignedLength - lastend));
    }

    if (!softEnd.empty()) {
        newCigar.push_back(CigarOp('S', softEnd.size()));
    }

    DEBUG(endl);

#ifdef VERBOSE_DEBUG
    if (debug) {
        for (vector<CigarOp>::const_iterator c = alignment.CigarData.begin();
            c != alignment.CigarData.end(); ++c) {
            unsigned int l = c->Length;
            char t = c->Type;
            cerr << l << t;
        }
        cerr << endl;
    }
#endif

    alignment.CigarData = newCigar;

    for (vector<CigarOp>::const_iterator c = alignment.CigarData.begin();
        c != alignment.CigarData.end(); ++c) {
        unsigned int l = c->Length;
        char t = c->Type;
        cigar_after << l << t;
    }
    DEBUG(cigar_after.str() << endl);

    // check if we're realigned
    if (cigar_after.str() == cigar_before.str()) {
        return false;
    } else {
        return true;
    }

}

// Iteratively left-aligns the indels in the alignment until we have a stable
// realignment.  Returns true on realignment success or non-realignment.
// Returns false if we exceed the maximum number of realignment iterations.
//
bool stablyLeftAlign(BamAlignment& alignment, string referenceSequence, int maxiterations, bool debug) {

    if (!leftAlign(alignment, referenceSequence, debug)) {

        DEBUG("did not realign" << endl);
        return true;

    } else {

        while (leftAlign(alignment, referenceSequence, debug) && --maxiterations > 0) {
            DEBUG("realigning ..." << endl);
        }

        if (maxiterations <= 0) {
            return false;
        } else {
            return true;
        }

    }
}
<commit_msg>move flanking sequence of deletion right, moving deletion left<commit_after>#include "LeftAlign.h"

//bool debug;

// Attempts to left-realign all the indels represented by the alignment cigar.
//
// This is done by shifting all indels as far left as they can go without
// mismatch, then merging neighboring indels of the same class.  leftAlign
// updates the alignment cigar with changes, and returns true if realignment
// changed the alignment cigar.
//
// To left-align, we move multi-base indels left by their own length as long as
// the preceding bases match the inserted or deleted sequence.  After this
// step, we handle multi-base homopolymer indels by shifting them one base to
// the left until they mismatch the reference.
//
// To merge neighboring indels, we iterate through the set of left-stabilized
// indels.  For each indel we add a new cigar element to the new cigar.  If a
// deletion follows a deletion, or an insertion occurs at the same place as
// another insertion, we merge the events by extending the previous cigar
// element.
//
// In practice, we must call this function until the alignment is stabilized.
//
bool leftAlign(BamAlignment& alignment, string& referenceSequence, bool debug) {

    int arsOffset = 0; // pointer to insertion point in aligned reference sequence
    string alignedReferenceSequence = referenceSequence;
    int aabOffset = 0;
    string alignmentAlignedBases = alignment.QueryBases;

    // store information about the indels
    vector<IndelAllele> indels;

    int rp = 0;  // read position, 0-based relative to read
    int sp = 0;  // sequence position

    string softBegin;
    string softEnd;

    stringstream cigar_before, cigar_after;
    for (vector<CigarOp>::const_iterator c = alignment.CigarData.begin();
        c != alignment.CigarData.end(); ++c) {
        unsigned int l = c->Length;
        char t = c->Type;
        cigar_before << l << t;
        if (t == 'M') { // match or mismatch
            sp += l;
            rp += l;
        } else if (t == 'D') { // deletion
            indels.push_back(IndelAllele(false, l, sp, rp, referenceSequence.substr(sp, l)));
            alignmentAlignedBases.insert(rp + aabOffset, string(l, '-'));
            aabOffset += l;
            sp += l;  // update sample position
        } else if (t == 'I') { // insertion
            indels.push_back(IndelAllele(true, l, sp, rp, alignment.QueryBases.substr(rp, l)));
            alignedReferenceSequence.insert(sp + softBegin.size() + arsOffset, string(l, '-'));
            arsOffset += l;
            rp += l;
        } else if (t == 'S') { // soft clip, clipped sequence present in the read not matching the reference
            // remove these bases from the refseq and read seq, but don't modify the alignment sequence
            if (rp == 0) {
                alignedReferenceSequence = string(l, '*') + alignedReferenceSequence;
                softBegin = alignmentAlignedBases.substr(0, l);
            } else {
                alignedReferenceSequence = alignedReferenceSequence + string(l, '*');
                softEnd = alignmentAlignedBases.substr(alignmentAlignedBases.size() - l, l);
            }
            rp += l;
        } else if (t == 'H') { // hard clip on the read, clipped sequence is not present in the read
        } else if (t == 'N') { // skipped region in the reference not present in read, aka splice
            sp += l;
        }
    }

    int alignedLength = sp;

    DEBUG("| " << cigar_before.str() << endl
       << "| " << alignedReferenceSequence << endl
       << "| " << alignmentAlignedBases << endl);

    // if no indels, return the alignment
    if (indels.empty()) { return false; }

    // for each indel, from left to right
    //     while the indel sequence repeated to the left and we're not matched up with the left-previous indel
    //         move the indel left

    vector<IndelAllele>::iterator previous = indels.begin();
    for (vector<IndelAllele>::iterator id = indels.begin(); id != indels.end(); ++id) {
        IndelAllele& indel = *id;
        int steppos = indel.position - indel.length;
        int readsteppos = (indel.insertion ? indel.readPosition - indel.length : indel.readPosition) - 1;
        // repeated subunits, single base homopolymers
        while (steppos >= 0 && readsteppos >= 0
               && indel.sequence == referenceSequence.substr(steppos, indel.length)
               && indel.sequence == alignment.QueryBases.substr(readsteppos, indel.length)
               && (id == indels.begin()
                   || (previous->insertion && steppos >= previous->position)
                   || (!previous->insertion && steppos >= previous->position + previous->length))) {
            DEBUG("indel " << indel << " shifting " << indel.length << "bp left" << endl);
            indel.position -= indel.length;
            indel.readPosition -= indel.length;
            steppos = indel.position - indel.length;
            readsteppos = (indel.insertion ? indel.readPosition - indel.length : indel.readPosition) - 1;
        }
        // multi-base homopolymers
        if (indel.homopolymer()) {
            while (indel.position > 0
                   && indel.sequence == referenceSequence.substr(indel.position - 1, indel.length)
                   && indel.sequence == alignment.QueryBases.substr(indel.readPosition - 1, indel.length)
                   && (id == indels.begin() || indel.position >= previous->position + previous->length)) {
                DEBUG("indel " << indel << " shifting " << 1 << "bp left" << endl);
                indel.position -= 1;
                indel.readPosition -= 1;
            }
        }
        // deletions with exchangeable flanking sequence
        if (!indel.insertion) {
            while (indel.position > 0
                   && indel.sequence.at(indel.sequence.size() - 1) == referenceSequence.at(indel.position - 1)
                   && (id == indels.begin() || indel.position >= previous->position + previous->length)) {
                indel.sequence = indel.sequence.at(indel.sequence.size() - 1) + indel.sequence.substr(0, indel.sequence.size() - 1);
                indel.position -= 1;
                indel.readPosition -= 1;
            }
        }
        previous = id;
    }

    // unhandled:
    // attempt to shift in lengths below the tandem dup size
    // replaces above loop, but...
    // buggy code:
    /*
    vector<IndelAllele>::iterator previous = indels.begin();
    for (vector<IndelAllele>::iterator id = indels.begin(); id != indels.end(); ++id) {
        IndelAllele& indel = *id;
        int steppos = indel.position - indel.length;
        int step = indel.length;
        while (steppos >= 0 && step > 0) {
            step = indel.length;
            steppos = indel.position - step;
            while (step > 0) {
                DEBUG(step << endl);
                if (indel.sequence == referenceSequence.substr(steppos, indel.length)
                   && (id == indels.begin()
                       || (previous->insertion && steppos >= previous->position)
                       || (!previous->insertion && steppos >= previous->position + previous->length))) {

                    DEBUG("indel " << indel << " shifting " << indel.length << "bp left" << endl);
                    indel.position -= step;
                    steppos = indel.position;
                    break;
                } else {
                    --step;
                }
            }
        }
        // multi-base homopolymers
        previous = id;
    }
       */

    // bring together floating indels
    // from left to right
    // check if we could merge with the next indel
    // if so, adjust so that we will merge in the next step
    if (indels.size() > 1) {
        previous = indels.begin();
        for (vector<IndelAllele>::iterator id = (indels.begin() + 1); id != indels.end(); ++id) {
            IndelAllele& indel = *id;
            // could we shift right and merge with the previous indel?
            // if so, do it
            int prev_end = previous->insertion ? previous->position : previous->position + previous->length;
            if (previous->insertion == indel.insertion
                    && ((previous->insertion && previous->position < indel.position)
                        ||
                        (!previous->insertion && previous->position + previous->length < indel.position))) {
                if (previous->homopolymer()) {
                    string seq = referenceSequence.substr(prev_end, indel.position - prev_end);
                    if (previous->sequence.at(0) == seq.at(0) && homopolymer(seq)) {
                        DEBUG("moving " << *previous << " right to "
                                << (indel.insertion ? indel.position : indel.position - previous->length) << endl);
                        previous->position = indel.insertion ? indel.position : indel.position - previous->length;
                    }
                }
                else {
                    int pos = previous->position;
                    while (pos < (int) referenceSequence.length() &&
                            ((previous->insertion && pos + previous->length <= indel.position)
                            ||
                            (!previous->insertion && pos + previous->length < indel.position))
                            && previous->sequence
                                == referenceSequence.substr(pos + previous->length, previous->length)) {
                        pos += previous->length;
                    }
                    if (pos < previous->position &&
                        ((previous->insertion && pos + previous->length == indel.position)
                        ||
                        (!previous->insertion && pos == indel.position - previous->length))
                       ) {
                        DEBUG("right-merging tandem repeat: moving " << *previous << " right to " << pos << endl);
                        previous->position = pos;
                    }
                }
            }
        }
    }

    // for each indel
    //     if ( we're matched up to the previous insertion (or deletion)
    //          and it's also an insertion or deletion )
    //         merge the indels

    vector<CigarOp> newCigar;

    if (!softBegin.empty()) {
        newCigar.push_back(CigarOp('S', softBegin.size()));
    }

    vector<IndelAllele>::iterator id = indels.begin();
    IndelAllele last = *id++;
    if (last.position > 0) {
        newCigar.push_back(CigarOp('M', last.position));
        newCigar.push_back(CigarOp((last.insertion ? 'I' : 'D'), last.length));
    } else {
        newCigar.push_back(CigarOp((last.insertion ? 'I' : 'D'), last.length));
    }
    int lastend = last.insertion ? last.position : (last.position + last.length);
    DEBUG(last << ",");

    for (; id != indels.end(); ++id) {
        IndelAllele& indel = *id;
        DEBUG(indel << ",");
        if (indel.position < lastend) {
            cerr << "impossibility?: indel realigned left of another indel" << endl << alignment.Name
                << " " << alignment.Position << endl << alignment.QueryBases << endl;
            exit(1);
        } else if (indel.position == lastend && indel.insertion == last.insertion) {
            CigarOp& op = newCigar.back();
            op.Length += indel.length;
        } else if (indel.position > lastend) {
            newCigar.push_back(CigarOp('M', indel.position - lastend));
            newCigar.push_back(CigarOp((indel.insertion ? 'I' : 'D'), indel.length));
        }
        last = *id;
        lastend = last.insertion ? last.position : (last.position + last.length);
    }

    if ((last.position + last.length) < alignedLength) {
        newCigar.push_back(CigarOp('M', alignedLength - lastend));
    }

    if (!softEnd.empty()) {
        newCigar.push_back(CigarOp('S', softEnd.size()));
    }

    DEBUG(endl);

#ifdef VERBOSE_DEBUG
    if (debug) {
        for (vector<CigarOp>::const_iterator c = alignment.CigarData.begin();
            c != alignment.CigarData.end(); ++c) {
            unsigned int l = c->Length;
            char t = c->Type;
            cerr << l << t;
        }
        cerr << endl;
    }
#endif

    alignment.CigarData = newCigar;

    for (vector<CigarOp>::const_iterator c = alignment.CigarData.begin();
        c != alignment.CigarData.end(); ++c) {
        unsigned int l = c->Length;
        char t = c->Type;
        cigar_after << l << t;
    }
    DEBUG(cigar_after.str() << endl);

    // check if we're realigned
    if (cigar_after.str() == cigar_before.str()) {
        return false;
    } else {
        return true;
    }

}

// Iteratively left-aligns the indels in the alignment until we have a stable
// realignment.  Returns true on realignment success or non-realignment.
// Returns false if we exceed the maximum number of realignment iterations.
//
bool stablyLeftAlign(BamAlignment& alignment, string referenceSequence, int maxiterations, bool debug) {

    if (!leftAlign(alignment, referenceSequence, debug)) {

        DEBUG("did not realign" << endl);
        return true;

    } else {

        while (leftAlign(alignment, referenceSequence, debug) && --maxiterations > 0) {
            DEBUG("realigning ..." << endl);
        }

        if (maxiterations <= 0) {
            return false;
        } else {
            return true;
        }

    }
}
<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011.
// 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)
//=======================================================================

#include "FunctionContext.hpp"
#include "Labels.hpp"

#include "asm/Registers.hpp"

#include "ltac/Compiler.hpp"

#include "mtac/Utils.hpp" //TODO Perhaps this should be moved to ltac ?

using namespace eddic;

void add_instruction(std::shared_ptr<ltac::Function> function, ltac::Operator op, ltac::Argument arg1){
    function->add(std::make_shared<ltac::Instruction>(op, arg1));
}

void add_instruction(std::shared_ptr<ltac::Function> function, ltac::Operator op, ltac::Argument arg1, ltac::Argument arg2){
    function->add(std::make_shared<ltac::Instruction>(op, arg1, arg2));
}

void ltac::Compiler::compile(std::shared_ptr<mtac::Program> source, std::shared_ptr<ltac::Program> target){
    for(auto& src_function : source->functions){
        auto target_function = std::make_shared<ltac::Function>(src_function->context, src_function->getName());

        target->functions.push_back(target_function);

        compile(src_function, target_function);
    }
}

void ltac::Compiler::compile(std::shared_ptr<mtac::Function> src_function, std::shared_ptr<ltac::Function> target_function){
    auto size = src_function->context->size();

    //Only if necessary, allocates size on the stack for the local variables
    if(size > 0){
        add_instruction(target_function, ltac::Operator::ALLOC_STACK, size);
    }

    auto iter = src_function->context->begin();
    auto end = src_function->context->end();

    for(; iter != end; iter++){
        auto var = iter->second;
        if(var->type().isArray() && var->position().isStack()){
            int position = -var->position().offset();

            add_instruction(target_function, ltac::Operator::MOV, ltac::Address(ltac::BP, position), var->type().size());

            if(var->type().base() == BaseType::INT){
                add_instruction(target_function, ltac::Operator::MEMSET, ltac::Address(ltac::BP, position, -8), var->type().size());
            } else if(var->type().base() == BaseType::STRING){
                add_instruction(target_function, ltac::Operator::MEMSET, ltac::Address(ltac::BP, position, -8), 2 * var->type().size());
            }
        }
    }

    //Compute the block usage (in order to know if we have to output the label)
    mtac::computeBlockUsage(src_function, block_usage);

    resetNumbering();

    //First we computes a label for each basic block
    for(auto block : src_function->getBasicBlocks()){
        block->label = newLabel();
    }

    //Then we compile each of them
    for(auto block : src_function->getBasicBlocks()){
        compile(block, target_function);
    }

    //TODO Return optimization

    //Only if necessary, deallocates size on the stack for the local variables
    if(size > 0){
        add_instruction(target_function, ltac::Operator::FREE_STACK, size);
    }
}

void ltac::Compiler::compile(std::shared_ptr<mtac::BasicBlock> block, std::shared_ptr<ltac::Function> target_function){
    //Handle parameters

    //If necessary add a label for the block
    if(block_usage.find(block) != block_usage.end()){
        target_function->add(block->label);
    }

    //statements

    //end basic block
}

struct StatementCompiler : public boost::static_visitor<> {
    //The registers
    as::Registers<ltac::Register> registers;
    as::Registers<ltac::FloatRegister> float_registers;
};
<commit_msg>Init the registers<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011.
// 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)
//=======================================================================

#include "FunctionContext.hpp"
#include "Labels.hpp"

#include "asm/Registers.hpp"

#include "ltac/Compiler.hpp"

#include "mtac/Utils.hpp" //TODO Perhaps this should be moved to ltac ?

using namespace eddic;

void add_instruction(std::shared_ptr<ltac::Function> function, ltac::Operator op, ltac::Argument arg1){
    function->add(std::make_shared<ltac::Instruction>(op, arg1));
}

void add_instruction(std::shared_ptr<ltac::Function> function, ltac::Operator op, ltac::Argument arg1, ltac::Argument arg2){
    function->add(std::make_shared<ltac::Instruction>(op, arg1, arg2));
}

void ltac::Compiler::compile(std::shared_ptr<mtac::Program> source, std::shared_ptr<ltac::Program> target){
    for(auto& src_function : source->functions){
        auto target_function = std::make_shared<ltac::Function>(src_function->context, src_function->getName());

        target->functions.push_back(target_function);

        compile(src_function, target_function);
    }
}

void ltac::Compiler::compile(std::shared_ptr<mtac::Function> src_function, std::shared_ptr<ltac::Function> target_function){
    auto size = src_function->context->size();

    //Only if necessary, allocates size on the stack for the local variables
    if(size > 0){
        add_instruction(target_function, ltac::Operator::ALLOC_STACK, size);
    }

    auto iter = src_function->context->begin();
    auto end = src_function->context->end();

    for(; iter != end; iter++){
        auto var = iter->second;
        if(var->type().isArray() && var->position().isStack()){
            int position = -var->position().offset();

            add_instruction(target_function, ltac::Operator::MOV, ltac::Address(ltac::BP, position), var->type().size());

            if(var->type().base() == BaseType::INT){
                add_instruction(target_function, ltac::Operator::MEMSET, ltac::Address(ltac::BP, position, -8), var->type().size());
            } else if(var->type().base() == BaseType::STRING){
                add_instruction(target_function, ltac::Operator::MEMSET, ltac::Address(ltac::BP, position, -8), 2 * var->type().size());
            }
        }
    }

    //Compute the block usage (in order to know if we have to output the label)
    mtac::computeBlockUsage(src_function, block_usage);

    resetNumbering();

    //First we computes a label for each basic block
    for(auto block : src_function->getBasicBlocks()){
        block->label = newLabel();
    }

    //Then we compile each of them
    for(auto block : src_function->getBasicBlocks()){
        compile(block, target_function);
    }

    //TODO Return optimization

    //Only if necessary, deallocates size on the stack for the local variables
    if(size > 0){
        add_instruction(target_function, ltac::Operator::FREE_STACK, size);
    }
}

namespace {

struct StatementCompiler : public boost::static_visitor<> {
    //The registers
    as::Registers<ltac::Register> registers;
    as::Registers<ltac::FloatRegister> float_registers;

    StatementCompiler(std::vector<ltac::Register> registers, std::vector<ltac::FloatRegister> float_registers) :
            registers(registers, std::make_shared<Variable>("__fake_int__", newSimpleType(BaseType::INT), Position(PositionType::TEMPORARY))),
            float_registers(float_registers, std::make_shared<Variable>("__fake_float__", newSimpleType(BaseType::FLOAT), Position(PositionType::TEMPORARY))){
        //Nothing else to init
   }
};

} //end of anonymous namespace

void ltac::Compiler::compile(std::shared_ptr<mtac::BasicBlock> block, std::shared_ptr<ltac::Function> target_function){
    //Handle parameters

    //If necessary add a label for the block
    if(block_usage.find(block) != block_usage.end()){
        target_function->add(block->label);
    }

    //TODO Fill the registers
    StatementCompiler compiler({}, {});

    //statements

    //end basic block
}

<|endoftext|>


<commit_before>// ComDirver.cpp: implementation of the CComDirver class.
//
//////////////////////////////////////////////////////////////////////

#include "vmlua.h"
#include "lua/lua.hpp"

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

#include "hash.h"
#include "key.h"
#include "main.h"
#include <openssl/des.h>
#include <vector>
#include "vmrunevn.h"
#include "tx.h"
//#include "Typedef.h"

#if 0
typedef struct NumArray{
	int size;          // С
	double values[1];  //黺
}NumArray;

/*
 * ȡuserdatum*/
static NumArray *checkarray(lua_State *L){
	//ջָλõĶǷΪиֵmetatableuserdatum
    void *ud = luaL_checkudata(L,1,"LuaBook.array");
    luaL_argcheck(L,ud != NULL,1,"'array' expected");
    return (NumArray *)ud;
}
/*
 * ȡָ*/
static double *getelem(lua_State *L){
    NumArray *a = checkarray(L);
    int index = luaL_checkint(L,2);
    luaL_argcheck(L,1 <= index && index <= a->size,2,"index out of range");
    /*return element address*/
    return &a->values[index - 1];
}
/*
 * */
int newarray(lua_State *L){
   int n = luaL_checkint(L,1);   //֤ʵluaL_checknumberı
   size_t nbytes = sizeof(NumArray) + (n -1) * sizeof(double);

	/*һuserdatum ṩһLuaûԤrawڴ
          ָĴСһڴ棬Ӧuserdatumŵջ,ڴĵַ*/
   NumArray *a = (NumArray *)lua_newuserdata(L,nbytes);
   luaL_getmetatable(L,"LuaBook.array");   //ȡregistryеtnameӦmetatable
   lua_setmetatable(L,-2);   //ջΪλõĶmetatable  µuserdatum
   a->size = n;
   return 1; /*new userdatnum is already on the statck*/
}
/*
 * 洢Ԫ,array.set(array,index,value)*/
int setarray(lua_State *L){
#if 0
	NumArray *a = (NumArray *)lua_touserdata(L,1);
	int index = luaL_checkint(L,2);
    double value = luaL_checknumber(L,3);

    luaL_argcheck(L,a != NULL,1,"'array' expected");
    luaL_argcheck(L,1 <= index && index <= a->size,2,"index out of range");
    a->values[index -1] = value;
#else
    double newvalue = luaL_checknumber(L,3);
    *getelem(L) = newvalue;
#endif
	return 0;
}
/*
 * ȡһԪ*/
int getarray(lua_State *L){
#if 0
	NumArray *a = (NumArray *)lua_touserdata(L,1);
    int index = luaL_checkint(L,2);

    luaL_argcheck(L,a != NULL,1,"'array' expected");
    luaL_argcheck(L,1 <= index && index <= a->size,2,"index out of range");
    lua_pushnumber(L,a->values[index - 1]);
#else
    lua_pushnumber(L,*getelem(L));
#endif
    return 1;
}
/*
 * ȡĴС*/
int getsize(lua_State *L){
#if 0
	NumArray *a = (NumArray *)lua_touserdata(L,1);
	luaL_argcheck(L,a != NULL,1,"'array' expected");
#else
	NumArray *a = checkarray(L);
#endif
	lua_pushnumber(L,a->size);
	return 1;
}
static const struct luaL_Reg arraylib[] = {
		{"new",newarray},
		{"set",setarray},
		{"get",getarray},
		{"size",getsize},
		{NULL,NULL}
};
static int luaopen_array(lua_State *L){
	/*userdataҪõmetatable*/
	luaL_newmetatable(L,"LuaBook.array");
	luaL_openlib(L,"array",arraylib,0);

	/*now the statck has the metatable at index 1 and
	 * 'array' at index 2*/
    lua_pushstring(L,"__index");
    lua_pushstring(L,"get");
    lua_gettable(L,2); /*get array.get*/
    lua_settable(L,1); /*metatable.__index - array.get*/

    lua_pushstring(L,"__newindex");
    lua_pushstring(L,"set");
    lua_gettable(L,2); /*get array.get*/
    lua_settable(L,1); /*metatable.__newindex - array.get*/
	return 0;
}

#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CVmlua::CVmlua(const vector<unsigned char> & vRom, const vector<unsigned char> &InputData){
	unsigned long len = 0;
	/*vRom script,InputData contract*/
    memset(m_ExRam,0,sizeof(m_ExRam));
    memset(m_ExeFile,0,sizeof(m_ExeFile));

    len = vRom.size();
    if(len >= sizeof(m_ExeFile)){
    	throw runtime_error("CVmlua::CVmlua() length of vRom exceptions");
    }
	memcpy(m_ExeFile, &vRom[0], len);
	unsigned short count = InputData.size();//С4096ֽ
	if(count > sizeof(m_ExRam) - 2){
		throw runtime_error("CVmlua::CVmlua() length of contract > 4094");
	}
	memcpy(m_ExRam, &count, 2);
	memcpy(&m_ExRam[2], &InputData[0],count);
}

CVmlua::~CVmlua() {

}

#ifdef WIN_DLL
extern "C" __declspec(dllexport) int luaopen_mylib(lua_State *L);
#else
LUAMOD_API int luaopen_mylib(lua_State *L);
#endif

void vm_openlibs (lua_State *L) {

	static const luaL_Reg lualibs[] = {
			{ "base", luaopen_base },
			{ LUA_LOADLIBNAME, luaopen_package },
			{ LUA_TABLIBNAME, luaopen_table },
			{ LUA_MATHLIBNAME, luaopen_math },
			{ LUA_STRLIBNAME, luaopen_string},
			{ NULL, NULL }
	};

	const luaL_Reg *lib;

	for (lib = lualibs; lib->func; lib++) {
		luaL_requiref(L, lib->name, lib->func, 1);
		lua_pop(L, 1); /* remove lib */
	}
}

tuple<bool,string> CVmlua::syntaxcheck(bool bFile, const char* filePathOrContent, int len) {
	//1.Luaл
	lua_State *lua_state = luaL_newstate();
	if (NULL == lua_state) {
		LogPrint("vm", "luaL_newstate error\n");
		return std::make_tuple(false, string("luaL_newstate error\n"));
	}

	vm_openlibs(lua_state);
	//3.עԶģ
	luaL_requiref(lua_state, "mylib", luaopen_mylib, 1);

	int nRet = 0;
	if(bFile) {
		nRet = luaL_loadfile(lua_state, filePathOrContent);
	} else {
		nRet = luaL_loadbuffer(lua_state, (char *)filePathOrContent, len, "line");
	}
	if (nRet) {
		const char* errStr = lua_tostring(lua_state, -1);
		lua_close(lua_state);
		return std::make_tuple (false, string(errStr));
	}

	lua_close(lua_state);

	return std::make_tuple (true, string("OK"));
}

}
int64_t CVmlua::run(uint64_t maxstep,CVmRunEvn *pVmScriptRun) {
	 long long step = 0;
	 unsigned short count = 0;

	if((maxstep == 0) || (NULL == pVmScriptRun)){
		return -1;
	}

	//1.Luaл
   lua_State *lua_state = luaL_newstate();
   if(NULL == lua_state){
	   LogPrint("vm", "luaL_newstate error\n");
	   return -1;
   }
/*
   //2.ôעLua׼
   static const luaL_Reg lualibs[] =
   {
	   {"base",luaopen_base},
	   {LUA_LOADLIBNAME, luaopen_package},
//	   {LUA_COLIBNAME, luaopen_coroutine},
	   {LUA_TABLIBNAME, luaopen_table},
//	   {LUA_IOLIBNAME, luaopen_io},
//	   {LUA_OSLIBNAME, luaopen_os},
//	   {LUA_STRLIBNAME, luaopen_string},
//	   {LUA_MATHLIBNAME, luaopen_math},
//	   {LUA_UTF8LIBNAME, luaopen_utf8},
//	   {LUA_DBLIBNAME, luaopen_debug},
	   {NULL,NULL}
   };
   //3.עLua׼Ⲣջ

   const luaL_Reg *lib = lualibs;
   for(;lib->func != NULL;lib++)
   {
	   lib->func(lua_state);
	   lua_settop(lua_state,0);
   }

   //ҪĿ
   //luaL_openlibs(lua_state);
*/
   vm_openlibs(lua_state);
   //3.עԶģ
   luaL_requiref(lua_state,"mylib",luaopen_mylib,1);

   //4.luaűݺԼ
	lua_newtable(lua_state);    //½һ,ѹջ
	lua_pushnumber(lua_state,-1);
	lua_rawseti(lua_state,-2,0);
	memcpy(&count,m_ExRam,  2);//ƣԼС4096ֽ
    for(unsigned short n = 0;n < count;n++)
    {
        lua_pushinteger(lua_state,m_ExRam[2 + n]);// valueֵ
        lua_rawseti(lua_state,-2,n+1);  //set table at key 'n + 1'
    }
    lua_setglobal(lua_state,"contract");

    //pVmScriptRunָ룬Աãȥʹȫֱָ
    lua_pushlightuserdata(lua_state, pVmScriptRun);
    lua_setglobal(lua_state,"VmScriptRun");

    LogPrint("vm", "pVmScriptRun=%p\n",pVmScriptRun);

   //5.ؽű
    step = maxstep;

    if(luaL_loadbuffer(lua_state,(char *)m_ExeFile,strlen((char *)m_ExeFile),"line") || lua_pcallk(lua_state,0,0,0,0,NULL,&step))
    {
	   LogPrint("vm", "luaL_loadbuffer fail:%s\n", lua_tostring(lua_state,-1));
	   step = -1;
	   lua_close(lua_state);
	   LogPrint("vm", "run step=%ld\n",step);
	   return step;
    }

    //6.ƽãĬϹرգűûøñ
	pVmScriptRun->SetCheckAccount(false);
	int res = lua_getglobal(lua_state, "gCheckAccount");
	LogPrint("vm", "lua_getglobal:%d\n", res);

    if(LUA_TBOOLEAN == res)
    {
    	if(lua_isboolean(lua_state,-1))
    	{
    		bool bCheck = lua_toboolean(lua_state,-1);
    		LogPrint("vm", "lua_toboolean:%d\n", bCheck);
    		pVmScriptRun->SetCheckAccount(bCheck);
    	}
    }
    lua_pop(lua_state, 1);

    //7.رLua
	lua_close(lua_state);
	LogPrint("vm", "run step=%ld\n",step);
	return step;
}

<commit_msg>修正一个错误：去掉多余的大括号。<commit_after>// ComDirver.cpp: implementation of the CComDirver class.
//
//////////////////////////////////////////////////////////////////////

#include "vmlua.h"
#include "lua/lua.hpp"

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

#include "hash.h"
#include "key.h"
#include "main.h"
#include <openssl/des.h>
#include <vector>
#include "vmrunevn.h"
#include "tx.h"
//#include "Typedef.h"

#if 0
typedef struct NumArray{
	int size;          // С
	double values[1];  //黺
}NumArray;

/*
 * ȡuserdatum*/
static NumArray *checkarray(lua_State *L){
	//ջָλõĶǷΪиֵmetatableuserdatum
    void *ud = luaL_checkudata(L,1,"LuaBook.array");
    luaL_argcheck(L,ud != NULL,1,"'array' expected");
    return (NumArray *)ud;
}
/*
 * ȡָ*/
static double *getelem(lua_State *L){
    NumArray *a = checkarray(L);
    int index = luaL_checkint(L,2);
    luaL_argcheck(L,1 <= index && index <= a->size,2,"index out of range");
    /*return element address*/
    return &a->values[index - 1];
}
/*
 * */
int newarray(lua_State *L){
   int n = luaL_checkint(L,1);   //֤ʵluaL_checknumberı
   size_t nbytes = sizeof(NumArray) + (n -1) * sizeof(double);

	/*һuserdatum ṩһLuaûԤrawڴ
          ָĴСһڴ棬Ӧuserdatumŵջ,ڴĵַ*/
   NumArray *a = (NumArray *)lua_newuserdata(L,nbytes);
   luaL_getmetatable(L,"LuaBook.array");   //ȡregistryеtnameӦmetatable
   lua_setmetatable(L,-2);   //ջΪλõĶmetatable  µuserdatum
   a->size = n;
   return 1; /*new userdatnum is already on the statck*/
}
/*
 * 洢Ԫ,array.set(array,index,value)*/
int setarray(lua_State *L){
#if 0
	NumArray *a = (NumArray *)lua_touserdata(L,1);
	int index = luaL_checkint(L,2);
    double value = luaL_checknumber(L,3);

    luaL_argcheck(L,a != NULL,1,"'array' expected");
    luaL_argcheck(L,1 <= index && index <= a->size,2,"index out of range");
    a->values[index -1] = value;
#else
    double newvalue = luaL_checknumber(L,3);
    *getelem(L) = newvalue;
#endif
	return 0;
}
/*
 * ȡһԪ*/
int getarray(lua_State *L){
#if 0
	NumArray *a = (NumArray *)lua_touserdata(L,1);
    int index = luaL_checkint(L,2);

    luaL_argcheck(L,a != NULL,1,"'array' expected");
    luaL_argcheck(L,1 <= index && index <= a->size,2,"index out of range");
    lua_pushnumber(L,a->values[index - 1]);
#else
    lua_pushnumber(L,*getelem(L));
#endif
    return 1;
}
/*
 * ȡĴС*/
int getsize(lua_State *L){
#if 0
	NumArray *a = (NumArray *)lua_touserdata(L,1);
	luaL_argcheck(L,a != NULL,1,"'array' expected");
#else
	NumArray *a = checkarray(L);
#endif
	lua_pushnumber(L,a->size);
	return 1;
}
static const struct luaL_Reg arraylib[] = {
		{"new",newarray},
		{"set",setarray},
		{"get",getarray},
		{"size",getsize},
		{NULL,NULL}
};
static int luaopen_array(lua_State *L){
	/*userdataҪõmetatable*/
	luaL_newmetatable(L,"LuaBook.array");
	luaL_openlib(L,"array",arraylib,0);

	/*now the statck has the metatable at index 1 and
	 * 'array' at index 2*/
    lua_pushstring(L,"__index");
    lua_pushstring(L,"get");
    lua_gettable(L,2); /*get array.get*/
    lua_settable(L,1); /*metatable.__index - array.get*/

    lua_pushstring(L,"__newindex");
    lua_pushstring(L,"set");
    lua_gettable(L,2); /*get array.get*/
    lua_settable(L,1); /*metatable.__newindex - array.get*/
	return 0;
}

#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CVmlua::CVmlua(const vector<unsigned char> & vRom, const vector<unsigned char> &InputData){
	unsigned long len = 0;
	/*vRom script,InputData contract*/
    memset(m_ExRam,0,sizeof(m_ExRam));
    memset(m_ExeFile,0,sizeof(m_ExeFile));

    len = vRom.size();
    if(len >= sizeof(m_ExeFile)){
    	throw runtime_error("CVmlua::CVmlua() length of vRom exceptions");
    }
	memcpy(m_ExeFile, &vRom[0], len);
	unsigned short count = InputData.size();//С4096ֽ
	if(count > sizeof(m_ExRam) - 2){
		throw runtime_error("CVmlua::CVmlua() length of contract > 4094");
	}
	memcpy(m_ExRam, &count, 2);
	memcpy(&m_ExRam[2], &InputData[0],count);
}

CVmlua::~CVmlua() {

}

#ifdef WIN_DLL
extern "C" __declspec(dllexport) int luaopen_mylib(lua_State *L);
#else
LUAMOD_API int luaopen_mylib(lua_State *L);
#endif

void vm_openlibs (lua_State *L) {

	static const luaL_Reg lualibs[] = {
			{ "base", luaopen_base },
			{ LUA_LOADLIBNAME, luaopen_package },
			{ LUA_TABLIBNAME, luaopen_table },
			{ LUA_MATHLIBNAME, luaopen_math },
			{ LUA_STRLIBNAME, luaopen_string},
			{ NULL, NULL }
	};

	const luaL_Reg *lib;

	for (lib = lualibs; lib->func; lib++) {
		luaL_requiref(L, lib->name, lib->func, 1);
		lua_pop(L, 1); /* remove lib */
	}
}

tuple<bool,string> CVmlua::syntaxcheck(bool bFile, const char* filePathOrContent, int len) {
	//1.Luaл
	lua_State *lua_state = luaL_newstate();
	if (NULL == lua_state) {
		LogPrint("vm", "luaL_newstate error\n");
		return std::make_tuple(false, string("luaL_newstate error\n"));
	}

	vm_openlibs(lua_state);
	//3.עԶģ
	luaL_requiref(lua_state, "mylib", luaopen_mylib, 1);

	int nRet = 0;
	if(bFile) {
		nRet = luaL_loadfile(lua_state, filePathOrContent);
	} else {
		nRet = luaL_loadbuffer(lua_state, (char *)filePathOrContent, len, "line");
	}
	if (nRet) {
		const char* errStr = lua_tostring(lua_state, -1);
		lua_close(lua_state);
		return std::make_tuple (false, string(errStr));
	}

	lua_close(lua_state);

	return std::make_tuple (true, string("OK"));
}

int64_t CVmlua::run(uint64_t maxstep,CVmRunEvn *pVmScriptRun) {
	 long long step = 0;
	 unsigned short count = 0;

	if((maxstep == 0) || (NULL == pVmScriptRun)){
		return -1;
	}

	//1.Luaл
   lua_State *lua_state = luaL_newstate();
   if(NULL == lua_state){
	   LogPrint("vm", "luaL_newstate error\n");
	   return -1;
   }
/*
   //2.ôעLua׼
   static const luaL_Reg lualibs[] =
   {
	   {"base",luaopen_base},
	   {LUA_LOADLIBNAME, luaopen_package},
//	   {LUA_COLIBNAME, luaopen_coroutine},
	   {LUA_TABLIBNAME, luaopen_table},
//	   {LUA_IOLIBNAME, luaopen_io},
//	   {LUA_OSLIBNAME, luaopen_os},
//	   {LUA_STRLIBNAME, luaopen_string},
//	   {LUA_MATHLIBNAME, luaopen_math},
//	   {LUA_UTF8LIBNAME, luaopen_utf8},
//	   {LUA_DBLIBNAME, luaopen_debug},
	   {NULL,NULL}
   };
   //3.עLua׼Ⲣջ

   const luaL_Reg *lib = lualibs;
   for(;lib->func != NULL;lib++)
   {
	   lib->func(lua_state);
	   lua_settop(lua_state,0);
   }

   //ҪĿ
   //luaL_openlibs(lua_state);
*/
   vm_openlibs(lua_state);
   //3.עԶģ
   luaL_requiref(lua_state,"mylib",luaopen_mylib,1);

   //4.luaűݺԼ
	lua_newtable(lua_state);    //½һ,ѹջ
	lua_pushnumber(lua_state,-1);
	lua_rawseti(lua_state,-2,0);
	memcpy(&count,m_ExRam,  2);//ƣԼС4096ֽ
    for(unsigned short n = 0;n < count;n++)
    {
        lua_pushinteger(lua_state,m_ExRam[2 + n]);// valueֵ
        lua_rawseti(lua_state,-2,n+1);  //set table at key 'n + 1'
    }
    lua_setglobal(lua_state,"contract");

    //pVmScriptRunָ룬Աãȥʹȫֱָ
    lua_pushlightuserdata(lua_state, pVmScriptRun);
    lua_setglobal(lua_state,"VmScriptRun");

    LogPrint("vm", "pVmScriptRun=%p\n",pVmScriptRun);

   //5.ؽű
    step = maxstep;

    if(luaL_loadbuffer(lua_state,(char *)m_ExeFile,strlen((char *)m_ExeFile),"line") || lua_pcallk(lua_state,0,0,0,0,NULL,&step))
    {
	   LogPrint("vm", "luaL_loadbuffer fail:%s\n", lua_tostring(lua_state,-1));
	   step = -1;
	   lua_close(lua_state);
	   LogPrint("vm", "run step=%ld\n",step);
	   return step;
    }

    //6.ƽãĬϹرգűûøñ
	pVmScriptRun->SetCheckAccount(false);
	int res = lua_getglobal(lua_state, "gCheckAccount");
	LogPrint("vm", "lua_getglobal:%d\n", res);

    if(LUA_TBOOLEAN == res)
    {
    	if(lua_isboolean(lua_state,-1))
    	{
    		bool bCheck = lua_toboolean(lua_state,-1);
    		LogPrint("vm", "lua_toboolean:%d\n", bCheck);
    		pVmScriptRun->SetCheckAccount(bCheck);
    	}
    }
    lua_pop(lua_state, 1);

    //7.رLua
	lua_close(lua_state);
	LogPrint("vm", "run step=%ld\n",step);
	return step;
}

<|endoftext|>


<commit_before>#include "utest.h"
#include "math/random.h"
#include "math/numeric.h"
#include "math/epsilon.h"
#include "functions/test.h"
#include "text/to_string.h"
#include "stoch_optimizer.h"

using namespace nano;

static void check_function(const function_t& function)
{
        const auto epochs = size_t(100);
        const auto epoch_size = size_t(1000);
        const auto trials = size_t(10);

        const auto dims = function.size();

        auto rgen = make_rng(scalar_t(-1), scalar_t(+1));

        // generate fixed random trials
        std::vector<vector_t> x0s(trials);
        for (auto& x0 : x0s)
        {
                x0.resize(dims);
                rgen(x0.data(), x0.data() + x0.size());
        }

        // optimizers to try
        const auto ids = get_stoch_optimizers().ids();
        for (const auto id : ids)
        {
                if (    id == "ngd" ||
                        id == "adadelta")
                {
                        // NGD may not decrease the function to epsilon!
                        // AdaDelta is not even guaranteed to decrease the function!
                        continue;
                }

                const auto optimizer = get_stoch_optimizers().get(id);

                size_t out_of_domain = 0;

                for (size_t t = 0; t < trials; ++ t)
                {
                        const auto& x0 = x0s[t];
                        const auto f0 = function.eval(x0);
                        const auto g_thres = epsilon2<scalar_t>();

                        // optimize
                        const auto params = stoch_params_t(epochs, epoch_size, epsilon1<scalar_t>());
                        const auto state = optimizer->minimize(params, function, x0);

                        const auto x = state.x;
                        const auto f = state.f;
                        const auto g = state.convergence_criteria();

                        // ignore out-of-domain solutions
                        if (!function.is_valid(x))
                        {
                                out_of_domain ++;
                                continue;
                        }

                        std::cout << function.name() << ", " << id
                                  << " [" << (t + 1) << "/" << trials << "]"
                                  << ": x = [" << x0.transpose() << "]/[" << x.transpose() << "]"
                                  << ", f = " << f0 << "/" << f
                                  << ", g = " << g << ".\n";

                        // check function value decrease
                        NANO_CHECK_LESS_EQUAL(f, f0);

                        // check convergence
                        NANO_CHECK_LESS_EQUAL(g, g_thres);
                }

                std::cout << function.name() << ", " << id
                          << ": out of domain " << out_of_domain << "/" << trials << ".\n";
        }
}

NANO_BEGIN_MODULE(test_stoch_optimizers)

NANO_CASE(evaluate)
{
        foreach_test_function(make_convex_functions(1, 2), check_function);
}

NANO_END_MODULE()

<commit_msg>faster unit test<commit_after>#include "utest.h"
#include "math/random.h"
#include "math/numeric.h"
#include "math/epsilon.h"
#include "functions/test.h"
#include "text/to_string.h"
#include "stoch_optimizer.h"

using namespace nano;

static void check_function(const function_t& function)
{
        const auto epochs = size_t(100);
        const auto epoch_size = size_t(1000);
        const auto trials = size_t(10);

        const auto dims = function.size();

        auto rgen = make_rng(scalar_t(-1), scalar_t(+1));

        // generate fixed random trials
        std::vector<vector_t> x0s(trials);
        for (auto& x0 : x0s)
        {
                x0.resize(dims);
                rgen(x0.data(), x0.data() + x0.size());
        }

        // optimizers to try
        const auto ids = get_stoch_optimizers().ids();
        for (const auto id : ids)
        {
                if (    id == "ngd" ||
                        id == "adadelta")
                {
                        // NGD may not decrease the function to epsilon!
                        // AdaDelta is not even guaranteed to decrease the function!
                        continue;
                }

                const auto optimizer = get_stoch_optimizers().get(id);

                size_t out_of_domain = 0;

                for (size_t t = 0; t < trials; ++ t)
                {
                        const auto& x0 = x0s[t];
                        const auto f0 = function.eval(x0);
                        const auto g_thres = epsilon2<scalar_t>();

                        // optimize
                        const auto params = stoch_params_t(epochs, epoch_size, epsilon2<scalar_t>());
                        const auto state = optimizer->minimize(params, function, x0);

                        const auto x = state.x;
                        const auto f = state.f;
                        const auto g = state.convergence_criteria();

                        // ignore out-of-domain solutions
                        if (!function.is_valid(x))
                        {
                                out_of_domain ++;
                                continue;
                        }

                        std::cout << function.name() << ", " << id
                                  << " [" << (t + 1) << "/" << trials << "]"
                                  << ": x = [" << x0.transpose() << "]/[" << x.transpose() << "]"
                                  << ", f = " << f0 << "/" << f
                                  << ", g = " << g << ".\n";

                        // check function value decrease
                        NANO_CHECK_LESS_EQUAL(f, f0);

                        // check convergence
                        NANO_CHECK_LESS_EQUAL(g, g_thres);
                }

                std::cout << function.name() << ", " << id
                          << ": out of domain " << out_of_domain << "/" << trials << ".\n";
        }
}

NANO_BEGIN_MODULE(test_stoch_optimizers)

NANO_CASE(evaluate)
{
        foreach_test_function(make_convex_functions(1, 2), check_function);
}

NANO_END_MODULE()

<|endoftext|>


<commit_before>// (C) 2014 Arek Olek

#pragma once

#include <chrono>
#include <random>
#include <tuple>

#include <boost/graph/graphml.hpp>

#include "algorithm.hpp"
#include "graph.hpp"

template <class Iterator>
void generate_seeds(Iterator begin, Iterator end, std::string seed) {
  std::seed_seq seq(seed.begin(), seed.end());
  seq.generate(begin, end);
}

double pr_within(double x) {
  return x <= 1
    ?  .5*x*x*x*x - 8./3*x*x*x + M_PI*x*x
    : -.5*x*x*x*x - 4*x*x*atan(sqrt(x*x-1)) + 4./3*(2*x*x+1)*sqrt(x*x-1) + (M_PI-2)*x*x + 1./3;
};

template <class Graph>
class test_suite {
public:
  unsigned size() const { return seeds.size() * degrees.size() * sizes.size(); }

  std::string type() const { return t; }

  std::tuple<Graph, unsigned, double, double> get(unsigned i) const {
    auto run = i % seeds.size();
    std::default_random_engine generator(seeds[run]);
    auto expected_degree = degrees[(i / seeds.size()) % degrees.size()];
    auto n = sizes[i / seeds.size() / degrees.size()];
    auto d = expected_degree;
    auto tree_degree = 2.*(n-1)/n;
    bool mst = found("mst", t);
    bool unite = !found("++", t);
    Graph G(n), G_shuffled(n);

    if(found("path", t)) {
      add_spider(G, 1, generator);
      // the overlap satisfies    y     = a    x     + b
      // full graph satisfies:    0     = a  (n-1)   + b
      // tree graph satisfies: 2(n-1)/n = a 2(n-1)/n + b
      // so we must subtract this:
      if(unite) d -= 2./(2.-n) * d + 1. + n/(n-2.);
    }

    double parameter;
    if(found("rgg", t)) {
      if(mst && unite) d -= d<2 ? tree_degree : 1/sinh(d-sqrt(2.)); // approximate fit
      parameter = find_argument(d/(n-1), pr_within, 0, sqrt(2.));
      Geometric points(n, generator);
      points.add_random_geometric(G, parameter);
      if(mst) points.add_mst(G);
    }
    else if(found("gnp", t)) {
      if(mst && unite) d -= d<2 ? tree_degree : 1/(2*M_PI*sinh(d-M_PI/sqrt(3.))); // approximate fit
      parameter = d<0 ? 0 : d/(n-1);
      add_edges_uniform(G, parameter, generator, mst);
    }

    copy_edges_shuffled(G, G_shuffled, generator);
    return std::make_tuple(G_shuffled, run, expected_degree, parameter);
  }

  template<class Sizes, class Degrees>
  test_suite(std::string t, unsigned z, Sizes ns, Degrees ds, std::string seed)
      : t(t), sizes(ns), degrees(ds) {
    seeds.resize(z);
    generate_seeds(seeds.begin(), seeds.end(), seed);
  }
private:
  std::string t;
  std::vector<unsigned> sizes;
  std::vector<double> degrees;
  std::vector<unsigned> seeds;
};

template <class Graph>
class file_suite {
public:
  std::tuple<Graph, unsigned, double, double> get(unsigned i) const {
    return std::make_tuple(graphs[i], i, 0, 0);
  }

  unsigned size() const { return graphs.size(); }

  file_suite(std::string f) : t(f.substr(0, f.find('.'))) {
    std::ifstream file(f);
    if(!file.good()) {
      throw std::invalid_argument("File does not exist: " + f);
    }
    int z, n, m, s, t;
    file >> z;
    while(z--) {
      file >> n >> m;
      Graph G(n);
      for(int i = 0; i < m; ++i) {
        file >> s >> t;
        add_edge(s, t, G);
      }
      graphs.push_back(G);
    }
    file.close();
  }
  std::string type() const {
    return t;
  }
private:
  std::string t;
  std::vector<Graph> graphs;
};

template <class Graph>
class real_suite {
public:
  unsigned size() const { return seeds.size(); }

  std::tuple<Graph, unsigned, double, double> get(unsigned i) const {
    std::default_random_engine generator(seeds[i]);
    Graph g(num_vertices(G));
    copy_edges_shuffled(G, g, generator);
    return std::make_tuple(g, i, 0, 0);
  }

  real_suite(std::string f, unsigned size, std::string seed)
      : G(0),
        t(f.substr(0, f.find('.'))),
        seeds(size) {
    std::ifstream file(f);
    if (!file.good()) {
      throw std::invalid_argument("File does not exist: " + f);
    }
    boost::dynamic_properties dp;
    read_graphml(file, G, dp);
    generate_seeds(seeds.begin(), seeds.end(), seed);
  }
  std::string type() const {
    return t;
  }
private:
  Graph G;
  std::string t;
  std::vector<unsigned> seeds;
};
<commit_msg>add special meaning to parameter -d when less than 1<commit_after>// (C) 2014 Arek Olek

#pragma once

#include <chrono>
#include <random>
#include <tuple>

#include <boost/graph/graphml.hpp>

#include "algorithm.hpp"
#include "graph.hpp"

template <class Iterator>
void generate_seeds(Iterator begin, Iterator end, std::string seed) {
  std::seed_seq seq(seed.begin(), seed.end());
  seq.generate(begin, end);
}

double pr_within(double x) {
  return x <= 1
    ?  .5*x*x*x*x - 8./3*x*x*x + M_PI*x*x
    : -.5*x*x*x*x - 4*x*x*atan(sqrt(x*x-1)) + 4./3*(2*x*x+1)*sqrt(x*x-1) + (M_PI-2)*x*x + 1./3;
};

template <class Graph>
class test_suite {
public:
  unsigned size() const { return seeds.size() * degrees.size() * sizes.size(); }

  std::string type() const { return t; }

  std::tuple<Graph, unsigned, double, double> get(unsigned i) const {
    auto run = i % seeds.size();
    std::default_random_engine generator(seeds[run]);
    auto expected_degree = degrees[(i / seeds.size()) % degrees.size()];
    auto n = sizes[i / seeds.size() / degrees.size()];
    auto d = expected_degree;
    auto tree_degree = 2.*(n-1)/n;
    bool mst = found("mst", t);
    bool unite = !found("++", t);
    Graph G(n), G_shuffled(n);

    // use d in [0,1] to mean density (since connected graphs have d > 1 anyway)
    if(unite && d <= 1) d *= n-1;

    if(found("path", t)) {
      add_spider(G, 1, generator);
      // the overlap satisfies    y     = a    x     + b
      // full graph satisfies:    0     = a  (n-1)   + b
      // tree graph satisfies: 2(n-1)/n = a 2(n-1)/n + b
      // so we must subtract this:
      if(unite) d -= 2./(2.-n) * d + 1. + n/(n-2.);
    }

    double parameter;
    if(found("rgg", t)) {
      if(mst && unite) d -= d<2 ? tree_degree : 1/sinh(d-sqrt(2.)); // approximate fit
      parameter = find_argument(d/(n-1), pr_within, 0, sqrt(2.));
      Geometric points(n, generator);
      points.add_random_geometric(G, parameter);
      if(mst) points.add_mst(G);
    }
    else if(found("gnp", t)) {
      if(mst && unite) d -= d<2 ? tree_degree : 1/(2*M_PI*sinh(d-M_PI/sqrt(3.))); // approximate fit
      parameter = d<0 ? 0 : d/(n-1);
      add_edges_uniform(G, parameter, generator, mst);
    }

    copy_edges_shuffled(G, G_shuffled, generator);
    return std::make_tuple(G_shuffled, run, expected_degree, parameter);
  }

  template<class Sizes, class Degrees>
  test_suite(std::string t, unsigned z, Sizes ns, Degrees ds, std::string seed)
      : t(t), sizes(ns), degrees(ds) {
    seeds.resize(z);
    generate_seeds(seeds.begin(), seeds.end(), seed);
  }
private:
  std::string t;
  std::vector<unsigned> sizes;
  std::vector<double> degrees;
  std::vector<unsigned> seeds;
};

template <class Graph>
class file_suite {
public:
  std::tuple<Graph, unsigned, double, double> get(unsigned i) const {
    return std::make_tuple(graphs[i], i, 0, 0);
  }

  unsigned size() const { return graphs.size(); }

  file_suite(std::string f) : t(f.substr(0, f.find('.'))) {
    std::ifstream file(f);
    if(!file.good()) {
      throw std::invalid_argument("File does not exist: " + f);
    }
    int z, n, m, s, t;
    file >> z;
    while(z--) {
      file >> n >> m;
      Graph G(n);
      for(int i = 0; i < m; ++i) {
        file >> s >> t;
        add_edge(s, t, G);
      }
      graphs.push_back(G);
    }
    file.close();
  }
  std::string type() const {
    return t;
  }
private:
  std::string t;
  std::vector<Graph> graphs;
};

template <class Graph>
class real_suite {
public:
  unsigned size() const { return seeds.size(); }

  std::tuple<Graph, unsigned, double, double> get(unsigned i) const {
    std::default_random_engine generator(seeds[i]);
    Graph g(num_vertices(G));
    copy_edges_shuffled(G, g, generator);
    return std::make_tuple(g, i, 0, 0);
  }

  real_suite(std::string f, unsigned size, std::string seed)
      : G(0),
        t(f.substr(0, f.find('.'))),
        seeds(size) {
    std::ifstream file(f);
    if (!file.good()) {
      throw std::invalid_argument("File does not exist: " + f);
    }
    boost::dynamic_properties dp;
    read_graphml(file, G, dp);
    generate_seeds(seeds.begin(), seeds.end(), seed);
  }
  std::string type() const {
    return t;
  }
private:
  Graph G;
  std::string t;
  std::vector<unsigned> seeds;
};
<|endoftext|>


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

#include <warnings.h>

#include <sync.h>
#include <util/system.h>
#include <util/translation.h>

static RecursiveMutex cs_warnings;
static std::string strMiscWarning GUARDED_BY(cs_warnings);
static bool fLargeWorkForkFound GUARDED_BY(cs_warnings) = false;
static bool fLargeWorkInvalidChainFound GUARDED_BY(cs_warnings) = false;

void SetMiscWarning(const std::string& strWarning)
{
    LOCK(cs_warnings);
    strMiscWarning = strWarning;
}

void SetfLargeWorkForkFound(bool flag)
{
    LOCK(cs_warnings);
    fLargeWorkForkFound = flag;
}

bool GetfLargeWorkForkFound()
{
    LOCK(cs_warnings);
    return fLargeWorkForkFound;
}

void SetfLargeWorkInvalidChainFound(bool flag)
{
    LOCK(cs_warnings);
    fLargeWorkInvalidChainFound = flag;
}

std::string GetWarnings(bool verbose)
{
    std::string warnings_concise;
    std::string warnings_verbose;
    const std::string uiAlertSeperator = "
";

    LOCK(cs_warnings);

    if (!CLIENT_VERSION_IS_RELEASE) {
        warnings_concise = "This is a pre-release test build - use at your own risk - do not use for mining or merchant applications";
        warnings_verbose = _("This is a pre-release test build - use at your own risk - do not use for mining or merchant applications").translated;
    }

    // Misc warnings like out of disk space and clock is wrong
    if (strMiscWarning != "")
    {
        warnings_concise = strMiscWarning;
        warnings_verbose += (warnings_verbose.empty() ? "" : uiAlertSeperator) + strMiscWarning;
    }

    if (fLargeWorkForkFound)
    {
        warnings_concise = "Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.";
        warnings_verbose += (warnings_verbose.empty() ? "" : uiAlertSeperator) + _("Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.").translated;
    }
    else if (fLargeWorkInvalidChainFound)
    {
        warnings_concise = "Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.";
        warnings_verbose += (warnings_verbose.empty() ? "" : uiAlertSeperator) + _("Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.").translated;
    }

    if (verbose) return warnings_verbose;
    else return warnings_concise;
}
<commit_msg>[style] Code style fixups in GetWarnings()<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <warnings.h>

#include <sync.h>
#include <util/system.h>
#include <util/translation.h>

static RecursiveMutex cs_warnings;
static std::string strMiscWarning GUARDED_BY(cs_warnings);
static bool fLargeWorkForkFound GUARDED_BY(cs_warnings) = false;
static bool fLargeWorkInvalidChainFound GUARDED_BY(cs_warnings) = false;

void SetMiscWarning(const std::string& strWarning)
{
    LOCK(cs_warnings);
    strMiscWarning = strWarning;
}

void SetfLargeWorkForkFound(bool flag)
{
    LOCK(cs_warnings);
    fLargeWorkForkFound = flag;
}

bool GetfLargeWorkForkFound()
{
    LOCK(cs_warnings);
    return fLargeWorkForkFound;
}

void SetfLargeWorkInvalidChainFound(bool flag)
{
    LOCK(cs_warnings);
    fLargeWorkInvalidChainFound = flag;
}

std::string GetWarnings(bool verbose)
{
    std::string warnings_concise;
    std::string warnings_verbose;
    const std::string warning_separator = "
";

    LOCK(cs_warnings);

    // Pre-release build warning
    if (!CLIENT_VERSION_IS_RELEASE) {
        warnings_concise = "This is a pre-release test build - use at your own risk - do not use for mining or merchant applications";
        warnings_verbose = _("This is a pre-release test build - use at your own risk - do not use for mining or merchant applications").translated;
    }

    // Misc warnings like out of disk space and clock is wrong
    if (strMiscWarning != "") {
        warnings_concise = strMiscWarning;
        warnings_verbose += (warnings_verbose.empty() ? "" : warning_separator) + strMiscWarning;
    }

    if (fLargeWorkForkFound) {
        warnings_concise = "Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.";
        warnings_verbose += (warnings_verbose.empty() ? "" : warning_separator) + _("Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.").translated;
    } else if (fLargeWorkInvalidChainFound) {
        warnings_concise = "Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.";
        warnings_verbose += (warnings_verbose.empty() ? "" : warning_separator) + _("Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.").translated;
    }

    if (verbose) return warnings_verbose;
    else return warnings_concise;
}
<|endoftext|>


<commit_before>
#include <windows.h>

#include "yacasprivate.h"
#include "lispenvironment.h"
#include "lispplugin.h"
#include "lispassert.h"
#include "platdll.h"

LispInt Win32Dll::Open(LispCharPtr aDllFile,LispEnvironment& aEnvironment)
{
    iDllFileName = aDllFile;
    handle = LoadLibrary(aDllFile);

    if (handle)
    {
        iPlugin = GetPlugin(aDllFile);
        if (iPlugin)
        {
            iPlugin->Add(aEnvironment);
        }
    }
    return (handle != NULL && iPlugin != NULL);
}

LispInt Win32Dll::Close(LispEnvironment& aEnvironment)
{
    if (iPlugin)
    {
        iPlugin->Remove(aEnvironment);
        delete iPlugin;
        iPlugin = NULL;
        return 1;
    }
    return 0;
}

Win32Dll::~Win32Dll()
{
    if (handle)
    {
        LISPASSERT(iPlugin == NULL);
        FreeLibrary((HMODULE) handle);
    }
    handle = NULL;
}
LispPluginBase* Win32Dll::GetPlugin(LispCharPtr aDllFile)
{
    LISPASSERT(handle != NULL);
    LispPluginBase* (*maker)(void);
    char buf[1024];
    //TODO potential buffer overflow!
    sprintf(buf,"make_%s",aDllFile);
    maker = (LispPluginBase*(*)(void))GetProcAddress((HMODULE)handle,buf);
    return maker();
}

<commit_msg>small patch to make windows version compile again.<commit_after>
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>

#include "yacasprivate.h"
#include "lispenvironment.h"
#include "lispplugin.h"
#include "lispassert.h"
#include "platdll.h"

LispInt Win32Dll::Open(LispCharPtr aDllFile,LispEnvironment& aEnvironment)
{
    iDllFileName = aDllFile;
    handle = LoadLibrary(aDllFile);

    if (handle)
    {
        iPlugin = GetPlugin(aDllFile);
        if (iPlugin)
        {
            iPlugin->Add(aEnvironment);
        }
    }
    return (handle != NULL && iPlugin != NULL);
}

LispInt Win32Dll::Close(LispEnvironment& aEnvironment)
{
    if (iPlugin)
    {
        iPlugin->Remove(aEnvironment);
        delete iPlugin;
        iPlugin = NULL;
        return 1;
    }
    return 0;
}

Win32Dll::~Win32Dll()
{
    if (handle)
    {
        LISPASSERT(iPlugin == NULL);
        FreeLibrary((HMODULE) handle);
    }
    handle = NULL;
}
LispPluginBase* Win32Dll::GetPlugin(LispCharPtr aDllFile)
{
    LISPASSERT(handle != NULL);
    LispPluginBase* (*maker)(void);
    char buf[1024];
    //TODO potential buffer overflow!
    sprintf(buf,"make_%s",aDllFile);
    maker = (LispPluginBase*(*)(void))GetProcAddress((HMODULE)handle,buf);
    return maker();
}

<|endoftext|>