<commit_before>/*++
Copyright (c) 2016 Microsoft Corporation

Module Name:

    bv_bounds_tactic.cpp

Abstract:

    Contextual bounds simplification tactic.

Author:

    Nikolaj Bjorner (nbjorner) 2016-2-12

--*/

#include "bv_bounds_tactic.h"
#include "ctx_simplify_tactic.h"
#include "bv_decl_plugin.h"
#include "ast_pp.h"

static rational uMaxInt(unsigned sz) {
    return rational::power_of_two(sz) - rational::one();
}

namespace {

struct interval {
    // l < h: [l, h]
    // l > h: [0, h] U [l, UMAX_INT]
    rational l, h;
    unsigned sz;
    bool tight;

    interval() {}
    interval(const rational& l, const rational& h, unsigned sz, bool tight = false) : l(l), h(h), sz(sz), tight(tight) {
        // canonicalize full set
        if (is_wrapped() && l == h + rational::one()) {
            this->l = rational::zero();
            this->h = uMaxInt(sz);
        }
        SASSERT(invariant());
    }

    bool invariant() const {
        return !l.is_neg() && !h.is_neg() && l <= uMaxInt(sz) && h <= uMaxInt(sz) &&
               (!is_wrapped() || l != h+rational::one());
    }

    bool is_full() const { return l.is_zero() && h == uMaxInt(sz); }
    bool is_wrapped() const { return l > h; }
    bool is_singleton() const { return l == h; }

    bool operator==(const interval& b) const {
        SASSERT(sz == b.sz);
        return l == b.l && h == b.h && tight == b.tight;
    }
    bool operator!=(const interval& b) const { return !(*this == b); }

    bool implies(const interval& b) const {
        if (b.is_full())
            return true;
        if (is_full())
            return false;

        if (is_wrapped()) {
            // l >= b.l >= b.h >= h
            return b.is_wrapped() && h <= b.h && l >= b.l;
        } else if (b.is_wrapped()) {
            // b.l > b.h >= h >= l
            // h >= l >= b.l > b.h
            return h <= b.h || l >= b.l;
        } else {
            //
            return l >= b.l && h <= b.h;
        }
    }

    /// return false if intersection is unsat
    bool intersect(const interval& b, interval& result) const {
        if (is_full() || *this == b) {
            result = b;
            return true;
        }
        if (b.is_full()) {
            result = *this;
            return true;
        }

        if (is_wrapped()) {
            if (b.is_wrapped()) {
                if (h >= b.l) {
                    result = b;
                } else if (b.h >= l) {
                    result = *this;
                } else {
                    result = interval(std::max(l, b.l), std::min(h, b.h), sz);
                }
            } else {
                return b.intersect(*this, result);
            }
        } else if (b.is_wrapped()) {
            // ... b.h ... l ... h ... b.l ..
            if (h < b.l && l > b.h) {
                return false;
            }
            // ... l ... b.l ... h ...
            if (h >= b.l && l <= b.h) {
                result = b;
            } else if (h >= b.l) {
                result = interval(b.l, h, sz);
            } else {
                // ... l .. b.h .. h .. b.l ...
                SASSERT(l <= b.h);
                result = interval(l, std::min(h, b.h), sz);
            }
        } else {
            if (l > b.h || h < b.l)
                return false;

            // 0 .. l.. l' ... h ... h'
            result = interval(std::max(l, b.l), std::min(h, b.h), sz, tight && b.tight);
        }
        return true;
    }

    /// return false if negation is empty
    bool negate(interval& result) const {
        if (!tight) {
            result = interval(rational::zero(), uMaxInt(sz), true);
            return true;
        }

        if (is_full())
            return false;
        if (l.is_zero()) {
            result = interval(h + rational::one(), uMaxInt(sz), sz);
        } else if (uMaxInt(sz) == h) {
            result = interval(rational::zero(), l - rational::one(), sz);
        } else {
            result = interval(h + rational::one(), l - rational::one(), sz);
        }
        return true;
    }
};

std::ostream& operator<<(std::ostream& o, const interval& I) {
    o << "[" << I.l << ", " << I.h << "]";
    return o;
}

struct undo_bound {
    expr* e;
    interval b;
    bool fresh;
    undo_bound(expr* e, const interval& b, bool fresh) : e(e), b(b), fresh(fresh) {}
};

class bv_bounds_simplifier : public ctx_simplify_tactic::simplifier {
    typedef obj_map<expr, interval> map;
    typedef obj_map<expr, bool> expr_set;
    typedef obj_map<expr, expr_set*> expr_list_map;

    ast_manager&       m;
    params_ref         m_params;
    bool               m_propagate_eq;
    bv_util            m_bv;
    vector<undo_bound> m_scopes;
    map                m_bound;
    expr_list_map      m_expr_vars;

    bool is_bound(expr *e, expr*& v, interval& b) const {
        rational n;
        expr *lhs, *rhs;
        unsigned sz;

        if (m_bv.is_bv_ule(e, lhs, rhs)) {
            if (m_bv.is_numeral(lhs, n, sz)) { // C ule x <=> x uge C
                if (m_bv.is_numeral(rhs))
                    return false;
                b = interval(n, uMaxInt(sz), sz, true);
                v = rhs;
                return true;
            }
            if (m_bv.is_numeral(rhs, n, sz)) { // x ule C
                b = interval(rational::zero(), n, sz, true);
                v = lhs;
                return true;
            }
        } else if (m_bv.is_bv_sle(e, lhs, rhs)) {
            if (m_bv.is_numeral(lhs, n, sz)) { // C sle x <=> x sge C
                if (m_bv.is_numeral(rhs))
                    return false;
                b = interval(n, rational::power_of_two(sz-1) - rational::one(), sz, true);
                v = rhs;
                return true;
            }
            if (m_bv.is_numeral(rhs, n, sz)) { // x sle C
                b = interval(rational::power_of_two(sz-1), n, sz, true);
                v = lhs;
                return true;
            }
        } else if (m.is_eq(e, lhs, rhs)) {
            if (m_bv.is_numeral(lhs, n, sz)) {
                if (m_bv.is_numeral(rhs))
                    return false;
                b = interval(n, n, sz, true);
                v = rhs;
                return true;
            }
            if (m_bv.is_numeral(rhs, n, sz)) {
                b = interval(n, n, sz, true);
                v = lhs;
                return true;
            }
        }
        return false;
    }

    expr_set* get_expr_vars(expr* t) {
        expr_set*& entry = m_expr_vars.insert_if_not_there2(t, 0)->get_data().m_value;
        if (entry)
            return entry;

        expr_set* set = alloc(expr_set);
        entry = set;

        if (!m_bv.is_numeral(t))
            set->insert(t, true);

        if (!is_app(t))
            return set;

        app* a = to_app(t);
        for (unsigned i = 0; i < a->get_num_args(); ++i) {
            expr_set* set_arg = get_expr_vars(a->get_arg(i));
            for (expr_set::iterator I = set_arg->begin(), E = set_arg->end(); I != E; ++I) {
                set->insert(I->m_key, true);
            }
        }
        return set;
    }

    bool expr_has_bounds(expr* t) {
        app* a = to_app(t);
        if ((m_bv.is_bv_ule(t) || m_bv.is_bv_sle(t) || m.is_eq(t)) &&
            (m_bv.is_numeral(a->get_arg(0)) || m_bv.is_numeral(a->get_arg(1))))
            return true;

        for (unsigned i = 0; i < a->get_num_args(); ++i) {
            if (expr_has_bounds(a->get_arg(i)))
                return true;
        }
        return false;
    }

public:

    bv_bounds_simplifier(ast_manager& m, params_ref const& p) : m(m), m_params(p), m_bv(m) {
        updt_params(p);
    }

    virtual void updt_params(params_ref const & p) {
        m_propagate_eq = p.get_bool("propagate_eq", false);
    }

    static void get_param_descrs(param_descrs& r) {
        r.insert("propagate-eq", CPK_BOOL, "(default: false) propagate equalities from inequalities");
    }

    virtual ~bv_bounds_simplifier() {
        for (expr_list_map::iterator I = m_expr_vars.begin(), E = m_expr_vars.end(); I != E; ++I) {
            dealloc(I->m_value);
        }
    }

    virtual bool assert_expr(expr * t, bool sign) {
        while (m.is_not(t, t)) {
            sign = !sign;
        }

        interval b;
        expr* t1;
        if (is_bound(t, t1, b)) {
            SASSERT(!m_bv.is_numeral(t1));
            if (sign)
                VERIFY(b.negate(b));

            TRACE("bv", tout << (sign?"(not ":"") << mk_pp(t, m) << (sign ? ")" : "") << ": " << mk_pp(t1, m) << " in " << b << "\n";);
            map::obj_map_entry* e = m_bound.find_core(t1);
            if (e) {
                interval& old = e->get_data().m_value;
                interval intr;
                if (!old.intersect(b, intr))
                    return false;
                if (old == intr)
                    return true;
                m_scopes.insert(undo_bound(t1, old, false));
                old = intr;
            } else {
                m_bound.insert(t1, b);
                m_scopes.insert(undo_bound(t1, interval(), true));
            }
        }
        return true;
    }

    virtual bool simplify(expr* t, expr_ref& result) {
        expr* t1;
        interval b;

        if (m_bound.find(t, b) && b.is_singleton()) {
            result = m_bv.mk_numeral(b.l, m_bv.get_bv_size(t));
            return true;
        }

        if (!m.is_bool(t))
            return false;

        bool sign = false;
        while (m.is_not(t, t)) {
            sign = !sign;
        }

        if (!is_bound(t, t1, b))
            return false;

        if (sign && b.tight) {
            sign = false;
            if (!b.negate(b)) {
                result = m.mk_false();
                return true;
            }
        }

        interval ctx, intr;
        result = 0;

        if (b.is_full() && b.tight) {
            result = m.mk_true();
        } else if (m_bound.find(t1, ctx)) {
            if (ctx.implies(b)) {
                result = m.mk_true();
            } else if (!b.intersect(ctx, intr)) {
                result = m.mk_false();
            } else if (m_propagate_eq && intr.is_singleton()) {
                result = m.mk_eq(t1, m_bv.mk_numeral(intr.l, m.get_sort(t1)));
            }
        }

        CTRACE("bv", result != 0, tout << mk_pp(t, m) << " " << b << " (ctx: " << ctx << ") (intr: " << intr << "): " << result << "\n";);
        if (sign && result != 0)
            result = m.mk_not(result);
        return result != 0;
    }

    virtual bool may_simplify(expr* t) {
        if (m_bv.is_numeral(t))
            return false;

        while (m.is_not(t, t));

        expr_set* used_exprs = get_expr_vars(t);
        for (map::iterator I = m_bound.begin(), E = m_bound.end(); I != E; ++I) {
            if (I->m_value.is_singleton() && used_exprs->contains(I->m_key))
                return true;
        }

        expr* t1;
        interval b;
        // skip common case: single bound constraint without any context for simplification
        if (is_bound(t, t1, b)) {
            return b.is_full() || m_bound.contains(t1);
        }
        return expr_has_bounds(t);
    }

    virtual void pop(unsigned num_scopes) {
        TRACE("bv", tout << "pop: " << num_scopes << "\n";);
        if (m_scopes.empty())
            return;
        unsigned target = m_scopes.size() - num_scopes;
        if (target == 0) {
            m_bound.reset();
            m_scopes.reset();
            return;
        }
        for (unsigned i = m_scopes.size()-1; i >= target; --i) {
            undo_bound& undo = m_scopes[i];
            SASSERT(m_bound.contains(undo.e));
            if (undo.fresh) {
                m_bound.erase(undo.e);
            } else {
                m_bound.insert(undo.e, undo.b);
            }
        }
        m_scopes.shrink(target);
    }

    virtual simplifier * translate(ast_manager & m) {
        return alloc(bv_bounds_simplifier, m, m_params);
    }

    virtual unsigned scope_level() const {
        return m_scopes.size();
    }
};

}

tactic * mk_bv_bounds_tactic(ast_manager & m, params_ref const & p) {
    return clean(alloc(ctx_simplify_tactic, m, alloc(bv_bounds_simplifier, m, p), p));
}
<commit_msg>bv_bounds: switch from rational to uint64 this limits the analysis to 64-bit BVs, but gives a speedup of up to one order of magnitude<commit_after>/*++
Copyright (c) 2016 Microsoft Corporation

Module Name:

    bv_bounds_tactic.cpp

Abstract:

    Contextual bounds simplification tactic.

Author:

    Nikolaj Bjorner (nbjorner) 2016-2-12

--*/

#include "bv_bounds_tactic.h"
#include "ctx_simplify_tactic.h"
#include "bv_decl_plugin.h"
#include "ast_pp.h"
#include <climits>

static uint64_t uMaxInt(unsigned sz) {
    SASSERT(sz <= 64);
    return ULLONG_MAX >> (64u - sz);
}

namespace {

struct interval {
    // l < h: [l, h]
    // l > h: [0, h] U [l, UMAX_INT]
    uint64_t l, h;
    unsigned sz;
    bool tight;

    interval() {}
    interval(uint64_t l, uint64_t h, unsigned sz, bool tight = false) : l(l), h(h), sz(sz), tight(tight) {
        // canonicalize full set
        if (is_wrapped() && l == h + 1) {
            this->l = 0;
            this->h = uMaxInt(sz);
        }
        SASSERT(invariant());
    }

    bool invariant() const {
        return l <= uMaxInt(sz) && h <= uMaxInt(sz) &&
               (!is_wrapped() || l != h+1);
    }

    bool is_full() const { return l == 0 && h == uMaxInt(sz); }
    bool is_wrapped() const { return l > h; }
    bool is_singleton() const { return l == h; }

    bool operator==(const interval& b) const {
        SASSERT(sz == b.sz);
        return l == b.l && h == b.h && tight == b.tight;
    }
    bool operator!=(const interval& b) const { return !(*this == b); }

    bool implies(const interval& b) const {
        if (b.is_full())
            return true;
        if (is_full())
            return false;

        if (is_wrapped()) {
            // l >= b.l >= b.h >= h
            return b.is_wrapped() && h <= b.h && l >= b.l;
        } else if (b.is_wrapped()) {
            // b.l > b.h >= h >= l
            // h >= l >= b.l > b.h
            return h <= b.h || l >= b.l;
        } else {
            //
            return l >= b.l && h <= b.h;
        }
    }

    /// return false if intersection is unsat
    bool intersect(const interval& b, interval& result) const {
        if (is_full() || *this == b) {
            result = b;
            return true;
        }
        if (b.is_full()) {
            result = *this;
            return true;
        }

        if (is_wrapped()) {
            if (b.is_wrapped()) {
                if (h >= b.l) {
                    result = b;
                } else if (b.h >= l) {
                    result = *this;
                } else {
                    result = interval(std::max(l, b.l), std::min(h, b.h), sz);
                }
            } else {
                return b.intersect(*this, result);
            }
        } else if (b.is_wrapped()) {
            // ... b.h ... l ... h ... b.l ..
            if (h < b.l && l > b.h) {
                return false;
            }
            // ... l ... b.l ... h ...
            if (h >= b.l && l <= b.h) {
                result = b;
            } else if (h >= b.l) {
                result = interval(b.l, h, sz);
            } else {
                // ... l .. b.h .. h .. b.l ...
                SASSERT(l <= b.h);
                result = interval(l, std::min(h, b.h), sz);
            }
        } else {
            if (l > b.h || h < b.l)
                return false;

            // 0 .. l.. l' ... h ... h'
            result = interval(std::max(l, b.l), std::min(h, b.h), sz, tight && b.tight);
        }
        return true;
    }

    /// return false if negation is empty
    bool negate(interval& result) const {
        if (!tight) {
            result = interval(0, uMaxInt(sz), true);
            return true;
        }

        if (is_full())
            return false;
        if (l == 0) {
            result = interval(h + 1, uMaxInt(sz), sz);
        } else if (uMaxInt(sz) == h) {
            result = interval(0, l - 1, sz);
        } else {
            result = interval(h + 1, l - 1, sz);
        }
        return true;
    }
};

std::ostream& operator<<(std::ostream& o, const interval& I) {
    o << "[" << I.l << ", " << I.h << "]";
    return o;
}

struct undo_bound {
    expr* e;
    interval b;
    bool fresh;
    undo_bound(expr* e, const interval& b, bool fresh) : e(e), b(b), fresh(fresh) {}
};

class bv_bounds_simplifier : public ctx_simplify_tactic::simplifier {
    typedef obj_map<expr, interval> map;
    typedef obj_map<expr, bool> expr_set;
    typedef obj_map<expr, expr_set*> expr_list_map;

    ast_manager&       m;
    params_ref         m_params;
    bool               m_propagate_eq;
    bv_util            m_bv;
    vector<undo_bound> m_scopes;
    map                m_bound;
    expr_list_map      m_expr_vars;
    expr_set           m_bound_exprs;

    bool is_number(expr *e, uint64_t& n, unsigned& sz) const {
        rational r;
        if (m_bv.is_numeral(e, r, sz) && sz <= 64) {
            n = r.get_uint64();
            return true;
        }
        return false;
    }

    bool is_bound(expr *e, expr*& v, interval& b) const {
        uint64_t n;
        expr *lhs, *rhs;
        unsigned sz;

        if (m_bv.is_bv_ule(e, lhs, rhs)) {
            if (is_number(lhs, n, sz)) { // C ule x <=> x uge C
                if (m_bv.is_numeral(rhs))
                    return false;
                b = interval(n, uMaxInt(sz), sz, true);
                v = rhs;
                return true;
            }
            if (is_number(rhs, n, sz)) { // x ule C
                b = interval(0, n, sz, true);
                v = lhs;
                return true;
            }
        } else if (m_bv.is_bv_sle(e, lhs, rhs)) {
            if (is_number(lhs, n, sz)) { // C sle x <=> x sge C
                if (m_bv.is_numeral(rhs))
                    return false;
                b = interval(n, (1ull << (sz-1)) - 1, sz, true);
                v = rhs;
                return true;
            }
            if (is_number(rhs, n, sz)) { // x sle C
                b = interval(1ull << (sz-1), n, sz, true);
                v = lhs;
                return true;
            }
        } else if (m.is_eq(e, lhs, rhs)) {
            if (is_number(lhs, n, sz)) {
                if (m_bv.is_numeral(rhs))
                    return false;
                b = interval(n, n, sz, true);
                v = rhs;
                return true;
            }
            if (is_number(rhs, n, sz)) {
                b = interval(n, n, sz, true);
                v = lhs;
                return true;
            }
        }
        return false;
    }

    expr_set* get_expr_vars(expr* t) {
        expr_set*& entry = m_expr_vars.insert_if_not_there2(t, 0)->get_data().m_value;
        if (entry)
            return entry;

        expr_set* set = alloc(expr_set);
        entry = set;

        if (!m_bv.is_numeral(t))
            set->insert(t, true);

        if (!is_app(t))
            return set;

        app* a = to_app(t);
        for (unsigned i = 0; i < a->get_num_args(); ++i) {
            expr_set* set_arg = get_expr_vars(a->get_arg(i));
            for (expr_set::iterator I = set_arg->begin(), E = set_arg->end(); I != E; ++I) {
                set->insert(I->m_key, true);
            }
        }
        return set;
    }

    bool expr_has_bounds(expr* t) {
        bool has_bounds = false;
        if (m_bound_exprs.find(t, has_bounds))
            return has_bounds;

        app* a = to_app(t);
        if ((m_bv.is_bv_ule(t) || m_bv.is_bv_sle(t) || m.is_eq(t)) &&
            (m_bv.is_numeral(a->get_arg(0)) || m_bv.is_numeral(a->get_arg(1)))) {
            has_bounds = true;
        }

        for (unsigned i = 0; !has_bounds && i < a->get_num_args(); ++i) {
            has_bounds = expr_has_bounds(a->get_arg(i));
        }

        m_bound_exprs.insert(t, has_bounds);
        return has_bounds;
    }

public:
    bv_bounds_simplifier(ast_manager& m, params_ref const& p) : m(m), m_params(p), m_bv(m) {
        updt_params(p);
    }

    virtual void updt_params(params_ref const & p) {
        m_propagate_eq = p.get_bool("propagate_eq", false);
    }

    static void get_param_descrs(param_descrs& r) {
        r.insert("propagate-eq", CPK_BOOL, "(default: false) propagate equalities from inequalities");
    }

    virtual ~bv_bounds_simplifier() {
        for (expr_list_map::iterator I = m_expr_vars.begin(), E = m_expr_vars.end(); I != E; ++I) {
            dealloc(I->m_value);
        }
    }

    virtual bool assert_expr(expr * t, bool sign) {
        while (m.is_not(t, t)) {
            sign = !sign;
        }

        interval b;
        expr* t1;
        if (is_bound(t, t1, b)) {
            SASSERT(!m_bv.is_numeral(t1));
            if (sign)
                VERIFY(b.negate(b));

            TRACE("bv", tout << (sign?"(not ":"") << mk_pp(t, m) << (sign ? ")" : "") << ": " << mk_pp(t1, m) << " in " << b << "\n";);
            map::obj_map_entry* e = m_bound.find_core(t1);
            if (e) {
                interval& old = e->get_data().m_value;
                interval intr;
                if (!old.intersect(b, intr))
                    return false;
                if (old == intr)
                    return true;
                m_scopes.insert(undo_bound(t1, old, false));
                old = intr;
            } else {
                m_bound.insert(t1, b);
                m_scopes.insert(undo_bound(t1, interval(), true));
            }
        }
        return true;
    }

    virtual bool simplify(expr* t, expr_ref& result) {
        expr* t1;
        interval b;

        if (m_bound.find(t, b) && b.is_singleton()) {
            result = m_bv.mk_numeral(b.l, m_bv.get_bv_size(t));
            return true;
        }

        if (!m.is_bool(t))
            return false;

        bool sign = false;
        while (m.is_not(t, t)) {
            sign = !sign;
        }

        if (!is_bound(t, t1, b))
            return false;

        if (sign && b.tight) {
            sign = false;
            if (!b.negate(b)) {
                result = m.mk_false();
                return true;
            }
        }

        interval ctx, intr;
        result = 0;

        if (b.is_full() && b.tight) {
            result = m.mk_true();
        } else if (m_bound.find(t1, ctx)) {
            if (ctx.implies(b)) {
                result = m.mk_true();
            } else if (!b.intersect(ctx, intr)) {
                result = m.mk_false();
            } else if (m_propagate_eq && intr.is_singleton()) {
                result = m.mk_eq(t1, m_bv.mk_numeral(rational(intr.l, rational::ui64()),
                                                     m.get_sort(t1)));
            }
        }

        CTRACE("bv", result != 0, tout << mk_pp(t, m) << " " << b << " (ctx: " << ctx << ") (intr: " << intr << "): " << result << "\n";);
        if (sign && result != 0)
            result = m.mk_not(result);
        return result != 0;
    }

    virtual bool may_simplify(expr* t) {
        if (m_bv.is_numeral(t))
            return false;

        while (m.is_not(t, t));

        expr_set* used_exprs = get_expr_vars(t);
        for (map::iterator I = m_bound.begin(), E = m_bound.end(); I != E; ++I) {
            if (I->m_value.is_singleton() && used_exprs->contains(I->m_key))
                return true;
        }

        expr* t1;
        interval b;
        // skip common case: single bound constraint without any context for simplification
        if (is_bound(t, t1, b)) {
            return b.is_full() || m_bound.contains(t1);
        }
        return expr_has_bounds(t);
    }

    virtual void pop(unsigned num_scopes) {
        TRACE("bv", tout << "pop: " << num_scopes << "\n";);
        if (m_scopes.empty())
            return;
        unsigned target = m_scopes.size() - num_scopes;
        if (target == 0) {
            m_bound.reset();
            m_scopes.reset();
            return;
        }
        for (unsigned i = m_scopes.size()-1; i >= target; --i) {
            undo_bound& undo = m_scopes[i];
            SASSERT(m_bound.contains(undo.e));
            if (undo.fresh) {
                m_bound.erase(undo.e);
            } else {
                m_bound.insert(undo.e, undo.b);
            }
        }
        m_scopes.shrink(target);
    }

    virtual simplifier * translate(ast_manager & m) {
        return alloc(bv_bounds_simplifier, m, m_params);
    }

    virtual unsigned scope_level() const {
        return m_scopes.size();
    }
};

}

tactic * mk_bv_bounds_tactic(ast_manager & m, params_ref const & p) {
    return clean(alloc(ctx_simplify_tactic, m, alloc(bv_bounds_simplifier, m, p), p));
}
<|endoftext|>


<commit_before>/*
 FILNAMN: 		NetClient.cc
 PROGRAMMERARE:	hanel742, eriek984, jened502, tobgr602, niker917, davha227
 SKAPAD DATUM:	2013-11-19
 BESKRIVNING:
 */

#include "NetClient.h"
#include "../Gui/Gui.h"
#include <QTest>

using namespace std;

NetClient::NetClient(string username, string inAddress, Gui* myGui, QObject *parent) : QObject(parent){

    guiPointer = myGui;
    name=QString::fromStdString(username);
    address=QString::fromStdString(inAddress);
}

void NetClient::start(){
    TcpSocket = new QTcpSocket(this);

    connect(TcpSocket,SIGNAL(connected()),this,SLOT(connected()));
    connect(TcpSocket,SIGNAL(disconnected()),this,SLOT(disconnected()));
    connect(TcpSocket,SIGNAL(readyRead()),this,SLOT(readyRead()));

    qDebug() << "connecting...";

    TcpSocket->connectToHost(QHostAddress(address),quint16(1234));

    if(!TcpSocket->waitForConnected(1000)){
        guiPointer->noConnection();
        qDebug() << "Error: " << TcpSocket->errorString();
    }
}

//------Slots---------

void NetClient::connected(){
    qDebug() << "Connected!";
    QByteArray array = "/initiate";
    array += 0x1F; //unit separator
    array += name;

    TcpSocket->write(array);
    TcpSocket->waitForBytesWritten(1000);
}

void NetClient::disconnected(){
    qDebug() << "disconnected";

}

void NetClient::readyRead(){
    //Recieve commando
    QByteArray Data = TcpSocket->readAll();

    // Separate the command from the operand
    QByteArray compare;
    compare += 0x1F;

    int i = Data.indexOf(compare);

    QString commandName = Data.left(i);
    QString inData = Data.mid(i);

    // Check which command that's supposed to run
    if (commandName == "/reinitiate") {
        guiPointer->userNameTaken();
    }

    else if (commandName == "/message") {

        // Get from
        i = inData.indexOf(compare);
        QString from = inData.left(i);
        inData = inData.mid(i);

        // Get to
        i = inData.indexOf(compare);
        QString to = inData.left(i);
        inData = inData.mid(i);

        // Get message
        i = inData.indexOf(compare);
        QString contents = inData.left(i);
        inData = inData.mid(i);

        // Get time
        QString dateTime = inData;

        guiPointer->receiveMessage(from, to, contents, dateTime);
    }
    else{
        throw logic_error("Unknown command, fatal error");
    }

}

void NetClient::sendMessage(QString from, QString to, QString message){
    QByteArray array = "/message";
    array += 0x1F; //unit separator
    array += from;
    array += 0x1F;
    array += to;
    array += 0x1F;
    array += message;

    TcpSocket->write(array);
    TcpSocket->waitForBytesWritten(1000);
}

void NetClient::setName(QString inName) {
    name=inName;
}

<commit_msg>changed in Netclient<commit_after>/*
 FILNAMN: 		NetClient.cc
 PROGRAMMERARE:	hanel742, eriek984, jened502, tobgr602, niker917, davha227
 SKAPAD DATUM:	2013-11-19
 BESKRIVNING:
 */

#include "NetClient.h"
#include "../Gui/Gui.h"
#include <QTest>

using namespace std;

NetClient::NetClient(QString username, QString inAddress, Gui* myGui, QObject *parent) : QObject(parent){

    guiPointer = myGui;
    name=username;
    address=inAddress;
}

void NetClient::start(){
    TcpSocket = new QTcpSocket(this);

    connect(TcpSocket,SIGNAL(connected()),this,SLOT(connected()));
    connect(TcpSocket,SIGNAL(disconnected()),this,SLOT(disconnected()));
    connect(TcpSocket,SIGNAL(readyRead()),this,SLOT(readyRead()));

    qDebug() << "connecting...";

    TcpSocket->connectToHost(QHostAddress(address),quint16(1234));

    if(!TcpSocket->waitForConnected(1000)){
        guiPointer->noConnection();
        qDebug() << "Error: " << TcpSocket->errorString();
    }
}

//------Slots---------

void NetClient::connected(){
    qDebug() << "Connected!";
    QByteArray array = "/initiate";
    array += 0x1F; //unit separator
    array += name;

    TcpSocket->write(array);
    TcpSocket->waitForBytesWritten(1000);
}

void NetClient::disconnected(){
    qDebug() << "disconnected";

}

void NetClient::readyRead(){
    //Recieve commando
    QByteArray Data = TcpSocket->readAll();

    // Separate the command from the operand
    QByteArray compare;
    compare += 0x1F;

    int i = Data.indexOf(compare);

    QString commandName = Data.left(i);
    QString inData = Data.mid(i);

    // Check which command that's supposed to run
    if (commandName == "/reinitiate") {
        guiPointer->userNameTaken();
    }

    else if (commandName == "/message") {

        // Get from
        i = inData.indexOf(compare);
        QString from = inData.left(i);
        inData = inData.mid(i);

        // Get to
        i = inData.indexOf(compare);
        QString to = inData.left(i);
        inData = inData.mid(i);

        // Get message
        i = inData.indexOf(compare);
        QString contents = inData.left(i);
        inData = inData.mid(i);

        // Get time
        QString dateTime = inData;

        guiPointer->receiveMessage(from, to, contents, dateTime);
    }
    else{
        throw logic_error("Unknown command, fatal error");
    }

}

void NetClient::sendMessage(QString from, QString to, QString message){
    QByteArray array = "/message";
    array += 0x1F; //unit separator
    array += from;
    array += 0x1F;
    array += to;
    array += 0x1F;
    array += message;

    TcpSocket->write(array);
    TcpSocket->waitForBytesWritten(1000);
}

void NetClient::setName(QString inName) {
    name=inName;
}

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013 The Native Client Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "native_client/tests/toolchain/eh_helper.h"

#include <math.h>

// Test that EH stack unwinding works when callee-saved floating point
// registers may be saved (e.g., on ARM).
// Also test that the callee-saved registers are restored during
// stack unwinding, for use in a catch-statement.

namespace {

// Make a float x 4, without including arch-specific headers.
typedef float v4sf __attribute__ ((__vector_size__(16)));

// Make it a union to help w/ accessing an individual element.
typedef union {
  float elems[4];
  v4sf v;
} Vec_4_f;

// Make some volatile constants to trick the optimizer.
volatile double kZero = 0.0;
volatile double kOne = 1.0;
volatile double kPiOver2 = M_PI_2;
volatile double kE = M_E;
volatile Vec_4_f kVOnes __attribute__((aligned(16))) = {
  { (float)kOne, (float)kOne, (float)kOne, (float)kOne }
};

// Make a function with roughly this structure:
// x, y, z = Heavy-Floating-Point-Compute;
// call();
// use(x, y, z);
//
// That makes it likely that x, y, z use callee-saved registers, instead of
// restoring values from the stack after the call.
void __attribute__((noinline)) outer(
    double x, double y, double z, double w);
void outer(double x, double y, double z, double w) {
  // Assume that the caller gives us appropriate values so that these
  // computations give 0 as the result.
  double should_be_zero1 = round(sqrt(x));
  double should_be_zero2 = round(cos(y));
  double should_be_zero3 = round(sin(z));
  double should_be_zero4 = round(log(w));
  double should_be_zero;
  Vec_4_f v_should_be_ones  __attribute__((aligned(16))),
      v_will_be_zeros  __attribute__((aligned(16)));
  v_should_be_ones.v = kVOnes.v;
  // Start v_will_be_zeros as all ones.
  // Then do v_will_be_zeros = <1...> * <1...> - <1...>.
  v_will_be_zeros.v = kVOnes.v;
  v_will_be_zeros.v =
      v_will_be_zeros.v * v_should_be_ones.v - v_should_be_ones.v;
  // Function call to make it worth using callee-saved regs.
  printf("Should be zero: %f, %f, %f, %f, %f\n",
         should_be_zero1, should_be_zero2, should_be_zero3, should_be_zero4,
         v_will_be_zeros.elems[0]);
  if (should_be_zero1 > should_be_zero2)
    should_be_zero = should_be_zero1;
  else if (should_be_zero2 > should_be_zero3)
    should_be_zero = should_be_zero2;
  else if (should_be_zero3 > should_be_zero4)
    should_be_zero = should_be_zero3;
  else
    should_be_zero = should_be_zero4;
  next_step(static_cast<int>(3 - should_be_zero));
  if (v_will_be_zeros.elems[0] > v_will_be_zeros.elems[1])
    throw static_cast<int>(v_will_be_zeros.elems[0]);
  else if (v_will_be_zeros.elems[1] > v_will_be_zeros.elems[2])
    throw static_cast<int>(v_will_be_zeros.elems[1]);
  else if (v_will_be_zeros.elems[2] > v_will_be_zeros.elems[3])
    throw static_cast<int>(v_will_be_zeros.elems[2]);
  else
    throw static_cast<int>(v_will_be_zeros.elems[3]);
}

}  // namespace

class B {
 public:
  explicit B(double should_be_one) {
    next_step(static_cast<int>(5 * should_be_one));
  }
  ~B() { next_step(7); }
};

void __attribute__((noinline)) middle(int never_55);
void middle(int never_55) {
  double should_be_one1 = sqrt(kOne) * cos(kZero);
  double should_be_one2 = sin(kPiOver2) * log(kE);
  Vec_4_f v_should_be_ones1 __attribute__((aligned(16))),
      v_should_be_ones2 __attribute__((aligned(16)));
  v_should_be_ones1.v = kVOnes.v;
  v_should_be_ones2.v = kVOnes.v;
  v_should_be_ones1.v = v_should_be_ones1.v * v_should_be_ones2.v;
  printf("Should be one: %f, %f, %f\n",
         should_be_one1, should_be_one2, v_should_be_ones1.elems[0]);
  try {
    // Function call to make it worth using callee-saved regs.
    outer(kZero, kPiOver2, kZero, kOne);
  } catch(int x) {
    if (x != 0)
      abort();
    printf("Should still be one: %f, %f, %f\n",
           should_be_one1, should_be_one2, v_should_be_ones1.elems[0]);
    // Floating point register restore is currently broken.
    // https://code.google.com/p/nativeclient/issues/detail?id=3672
    // Remove these assignments of 1.0 to test it.
    if (never_55 != 55) {
      should_be_one1 = 1.0;
      should_be_one2 = 1.0;
      v_should_be_ones1.elems[0] = 1.0;
    }
    next_step(4);
    if (should_be_one1 > should_be_one2) {
      throw B(should_be_one1);
    } else if (should_be_one2 > v_should_be_ones1.elems[0]) {
      throw B(should_be_one2);
    } else {
      throw B(v_should_be_ones1.elems[0]);
    }
  }
  abort();
}

int main(int argc, char* argv[]) {
  next_step(1);
  try {
    next_step(2);
    middle(argc);
  } catch(...) {
    next_step(6);
  }
  next_step(8);
  return 55;
}
<commit_msg>Turn on fp-restore part of eh_floating_point_*_test for PNaCl.<commit_after>/*
 * Copyright (c) 2013 The Native Client Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "native_client/tests/toolchain/eh_helper.h"

#include <assert.h>
#include <math.h>

// Test that EH stack unwinding works when callee-saved floating point
// registers may be saved (e.g., on ARM).
// Also test that the callee-saved registers are restored during
// stack unwinding, for use in a catch-statement.

namespace {

// Make a float x 4, without including arch-specific headers.
typedef float v4sf __attribute__ ((__vector_size__(16)));

// Make it a union to help w/ accessing an individual element.
typedef union {
  float elems[4];
  v4sf v;
} Vec_4_f;

// Make some volatile constants to trick the optimizer.
volatile double kZero = 0.0;
volatile double kOne = 1.0;
volatile double kPiOver2 = M_PI_2;
volatile double kE = M_E;
volatile Vec_4_f kVOnes __attribute__((aligned(16))) = {
  { (float)kOne, (float)kOne, (float)kOne, (float)kOne }
};

// Make a function with roughly this structure:
// x, y, z = Heavy-Floating-Point-Compute;
// call();
// use(x, y, z);
//
// That makes it likely that x, y, z use callee-saved registers, instead of
// restoring values from the stack after the call.
void __attribute__((noinline)) outer(
    double x, double y, double z, double w);
void outer(double x, double y, double z, double w) {
  // Assume that the caller gives us appropriate values so that these
  // computations give 0 as the result.
  double should_be_zero1 = round(sqrt(x));
  double should_be_zero2 = round(cos(y));
  double should_be_zero3 = round(sin(z));
  double should_be_zero4 = round(log(w));
  double should_be_zero;
  Vec_4_f v_should_be_ones  __attribute__((aligned(16))),
      v_will_be_zeros  __attribute__((aligned(16)));
  v_should_be_ones.v = kVOnes.v;
  // Start v_will_be_zeros as all ones.
  // Then do v_will_be_zeros = <1...> * <1...> - <1...>.
  v_will_be_zeros.v = kVOnes.v;
  v_will_be_zeros.v =
      v_will_be_zeros.v * v_should_be_ones.v - v_should_be_ones.v;
  // Function call to make it worth using callee-saved regs.
  printf("Should be zero: %f, %f, %f, %f, %f\n",
         should_be_zero1, should_be_zero2, should_be_zero3, should_be_zero4,
         v_will_be_zeros.elems[0]);
  if (should_be_zero1 > should_be_zero2)
    should_be_zero = should_be_zero1;
  else if (should_be_zero2 > should_be_zero3)
    should_be_zero = should_be_zero2;
  else if (should_be_zero3 > should_be_zero4)
    should_be_zero = should_be_zero3;
  else
    should_be_zero = should_be_zero4;
  next_step(static_cast<int>(3 - should_be_zero));
  if (v_will_be_zeros.elems[0] > v_will_be_zeros.elems[1])
    throw static_cast<int>(v_will_be_zeros.elems[0]);
  else if (v_will_be_zeros.elems[1] > v_will_be_zeros.elems[2])
    throw static_cast<int>(v_will_be_zeros.elems[1]);
  else if (v_will_be_zeros.elems[2] > v_will_be_zeros.elems[3])
    throw static_cast<int>(v_will_be_zeros.elems[2]);
  else
    throw static_cast<int>(v_will_be_zeros.elems[3]);
}

}  // namespace

class B {
 public:
  explicit B(double should_be_one) {
    next_step(static_cast<int>(5 * should_be_one));
  }
  ~B() { next_step(7); }
};

void __attribute__((noinline)) middle(int never_55);
void middle(int never_55) {
  double should_be_one1 = sqrt(kOne) * cos(kZero);
  double should_be_one2 = sin(kPiOver2) * log(kE);
  Vec_4_f v_should_be_ones1 __attribute__((aligned(16))),
      v_should_be_ones2 __attribute__((aligned(16)));
  v_should_be_ones1.v = kVOnes.v;
  v_should_be_ones2.v = kVOnes.v;
  v_should_be_ones1.v = v_should_be_ones1.v * v_should_be_ones2.v;
  printf("Should be one: %f, %f, %f\n",
         should_be_one1, should_be_one2, v_should_be_ones1.elems[0]);
  try {
    // Function call to make it worth using callee-saved regs.
    outer(kZero, kPiOver2, kZero, kOne);
  } catch(int x) {
    if (x != 0)
      abort();
    printf("Should still be one: %f, %f, %f\n",
           should_be_one1, should_be_one2, v_should_be_ones1.elems[0]);
    // Floating point register restore is currently broken.
    // https://code.google.com/p/nativeclient/issues/detail?id=3672
    // Remove these assignments of 1.0 to test it.
#if !defined(__pnacl__)
    if (never_55 != 55) {
      should_be_one1 = 1.0;
      should_be_one2 = 1.0;
      v_should_be_ones1.elems[0] = 1.0;
    }
#endif
    next_step(4);
    if (should_be_one1 > should_be_one2) {
      throw B(should_be_one1);
    } else if (should_be_one2 > v_should_be_ones1.elems[0]) {
      throw B(should_be_one2);
    } else {
      throw B(v_should_be_ones1.elems[0]);
    }
  }
  abort();
}

int main(int argc, char* argv[]) {
  double should_be_e = kE;
  double should_be_pi_2 = kPiOver2;
  double should_be_63 = sqrt(kOne) * cos(kZero) * 63;
  double should_be_127 = sin(kPiOver2) * log(kE) * 127;
  next_step(1);
  try {
    next_step(2);
    middle(argc);
  } catch(...) {
    fprintf(stderr, "should_be_e=%f, should_be_pi_2=%f, "
            "should_be_63=%f, shouldbe_127=%f\n",
            should_be_e, should_be_pi_2, should_be_63, should_be_127);
    // Floating point register restore is currently broken.
    // https://code.google.com/p/nativeclient/issues/detail?id=3672
#if !defined(__pnacl__)
    if (argc != 55) {
      should_be_e = kE;
      should_be_pi_2 = kPiOver2;
      should_be_63 = 63.0;
      should_be_127 = 127.0;
    }
#endif
    assert(should_be_e == kE);
    assert(should_be_pi_2 == kPiOver2);
    assert(should_be_63 == 63.0);
    assert(should_be_127 == 127.0);
    next_step(6);
  }
  next_step(8);
  return 55;
}
<|endoftext|>


<commit_before>//
//  Copyright (c) 2016 Terry Seyler
//
//  Distributed under the MIT License
//  See accompanying file LICENSE.md
//

#include <ostream>
#include <istream>
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
#include <core/client/proto_tcp_text_client.hpp>
#include <core/data/proto_net_error_data.hpp>

namespace proto_net
{
    namespace client
    {
         proto_tcp_text_client*
         proto_tcp_text_client::proto_tcp_text_client_cast(proto_service_ptr ps_ptr)
        {
            return dynamic_cast<proto_tcp_text_client*>(ps_ptr.get());
        }

        proto_tcp_text_client::proto_tcp_text_client(const std::string& address,
                                           unsigned short port_num /* = 80*/,
                                           proto_net_pipeline& ps_pipeline/* = empty_pipeline_inst*/,
                                           size_t buffer_size /*= 4096*/)
                : proto_tcp_client(address, port_num, ps_pipeline, buffer_size)
        {}

        proto_tcp_text_client::~proto_tcp_text_client()
        {}

        proto_tcp_text_client::proto_tcp_text_client(proto_net_service_ptr ps_service, const std::string& address,
                                                     unsigned short port_num /* = 80*/,
                                                     proto_net_pipeline& ps_pipeline/* = empty_pipeline_inst*/,
                                                     size_t buffer_size /*= 4096*/)
                : proto_tcp_client(ps_service, address, port_num, ps_pipeline, buffer_size)
        {}

        void
        proto_tcp_text_client::ps_async_read(void)
        {
            read_stream_buffer_.prepare(buffer_size_);
            boost::asio::async_read_until(socket_, read_stream_buffer_, '\0',
                                          boost::bind(&proto_tcp_text_client::ps_handle_read, this,
                                                      boost::asio::placeholders::error,
                                                      boost::asio::placeholders::bytes_transferred));
        }

        void
        proto_tcp_text_client::ps_async_write(proto_net_in_data& data_in)
        {

            if (data_in.data() && data_in.data_size() && data_in.data_type() == data_text) //guard against empty data getting put into the pipe in
            {
                if (ps_write_complete(max_wait_msec_)) // write is complete
                {
                    ps_pipeline_.ps_pipe_in(data_in); // just prior to the write, execute the pipe_in

                    char *data = data_in.data();
                    size_t data_size = data_in.data_size();
                    if (data && data_size)
                    {
                        boost::asio::async_write(socket_, boost::asio::buffer(data, data_size),
                                                 boost::bind(&proto_tcp_text_client::ps_handle_write, this,
                                                             boost::asio::placeholders::error,
                                                             boost::asio::placeholders::bytes_transferred));
                        write_complete_ = false;
                    }
                    else
                        ps_async_read(); // just go back to reading
                }
                else
                    ps_async_read(); // just go back to reading
            }
            else
                ps_async_read(); // just go back to reading
        }

        void
        proto_tcp_text_client::ps_handle_read(const boost::system::error_code& error, size_t bytes_transferred)
        {
            if (!error)
            {
                read_stream_buffer_.commit(bytes_transferred);
                std::istream is(&read_stream_buffer_);
             //   memset(buffer_, 0, buffer_size_);
                is.get(buffer_, buffer_size_, '\0');

                // handle a ps_read here
                std::string response(buffer_);
                proto_net_data res_data(response);
                std::string request;
                proto_net_data req_data(request);
                if (res_data.data_size())
                {
                    ps_pipeline_.ps_pipeline(res_data, req_data); // response and request are reversed here
                    ps_pipeline_.ps_pipe_out(res_data); // post read, execute the pipe_out for the client
                }
               // read_stream_buffer_.consume(read_stream_buffer_.size());
                read_stream_buffer_.consume(bytes_transferred);
               // read_stream_buffer_.prepare(buffer_size_);
                write_complete_ = true;

                ps_async_read(); // done go back to reading
            }
            else
            {
                proto_net_error_data err_data(ec_read_error);
                if (ps_pipeline_.ps_pipe_error(err_data))
                {
                    //delete this; // for now
                }
                else
                    ps_async_read(); // done go back to reading;
            }

        }

        void
        proto_tcp_text_client::ps_handle_write(const boost::system::error_code &error, size_t bytes_transferred)
        {
            if (!error)
            {
                // handle a post write here
                ps_async_read(); // just go back to reading
            }
            else
                delete this;
        }

    }
}<commit_msg>Removed commit.<commit_after>//
//  Copyright (c) 2016 Terry Seyler
//
//  Distributed under the MIT License
//  See accompanying file LICENSE.md
//

#include <ostream>
#include <istream>
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
#include <core/client/proto_tcp_text_client.hpp>
#include <core/data/proto_net_error_data.hpp>

namespace proto_net
{
    namespace client
    {
         proto_tcp_text_client*
         proto_tcp_text_client::proto_tcp_text_client_cast(proto_service_ptr ps_ptr)
        {
            return dynamic_cast<proto_tcp_text_client*>(ps_ptr.get());
        }

        proto_tcp_text_client::proto_tcp_text_client(const std::string& address,
                                           unsigned short port_num /* = 80*/,
                                           proto_net_pipeline& ps_pipeline/* = empty_pipeline_inst*/,
                                           size_t buffer_size /*= 4096*/)
                : proto_tcp_client(address, port_num, ps_pipeline, buffer_size)
        {}

        proto_tcp_text_client::~proto_tcp_text_client()
        {}

        proto_tcp_text_client::proto_tcp_text_client(proto_net_service_ptr ps_service, const std::string& address,
                                                     unsigned short port_num /* = 80*/,
                                                     proto_net_pipeline& ps_pipeline/* = empty_pipeline_inst*/,
                                                     size_t buffer_size /*= 4096*/)
                : proto_tcp_client(ps_service, address, port_num, ps_pipeline, buffer_size)
        {}

        void
        proto_tcp_text_client::ps_async_read(void)
        {
            read_stream_buffer_.prepare(buffer_size_);
            boost::asio::async_read_until(socket_, read_stream_buffer_, '\0',
                                          boost::bind(&proto_tcp_text_client::ps_handle_read, this,
                                                      boost::asio::placeholders::error,
                                                      boost::asio::placeholders::bytes_transferred));
        }

        void
        proto_tcp_text_client::ps_async_write(proto_net_in_data& data_in)
        {

            if (data_in.data() && data_in.data_size() && data_in.data_type() == data_text) //guard against empty data getting put into the pipe in
            {
                if (ps_write_complete(max_wait_msec_)) // write is complete
                {
                    ps_pipeline_.ps_pipe_in(data_in); // just prior to the write, execute the pipe_in

                    char *data = data_in.data();
                    size_t data_size = data_in.data_size();
                    if (data && data_size)
                    {
                        boost::asio::async_write(socket_, boost::asio::buffer(data, data_size),
                                                 boost::bind(&proto_tcp_text_client::ps_handle_write, this,
                                                             boost::asio::placeholders::error,
                                                             boost::asio::placeholders::bytes_transferred));
                        write_complete_ = false;
                    }
                    else
                        ps_async_read(); // just go back to reading
                }
                else
                    ps_async_read(); // just go back to reading
            }
            else
                ps_async_read(); // just go back to reading
        }

        void
        proto_tcp_text_client::ps_handle_read(const boost::system::error_code& error, size_t bytes_transferred)
        {
            if (!error)
            {
                //read_stream_buffer_.commit(bytes_transferred);
                std::istream is(&read_stream_buffer_);
             //   memset(buffer_, 0, buffer_size_);
                is.get(buffer_, buffer_size_, '\0');

                // handle a ps_read here
                std::string response(buffer_);
                proto_net_data res_data(response);
                std::string request;
                proto_net_data req_data(request);
                if (res_data.data_size())
                {
                    ps_pipeline_.ps_pipeline(res_data, req_data); // response and request are reversed here
                    ps_pipeline_.ps_pipe_out(res_data); // post read, execute the pipe_out for the client
                }
               // read_stream_buffer_.consume(read_stream_buffer_.size());
                read_stream_buffer_.consume(bytes_transferred);
               // read_stream_buffer_.prepare(buffer_size_);
                write_complete_ = true;

                ps_async_read(); // done go back to reading
            }
            else
            {
                proto_net_error_data err_data(ec_read_error);
                if (ps_pipeline_.ps_pipe_error(err_data))
                {
                    //delete this; // for now
                }
                else
                    ps_async_read(); // done go back to reading;
            }

        }

        void
        proto_tcp_text_client::ps_handle_write(const boost::system::error_code &error, size_t bytes_transferred)
        {
            if (!error)
            {
                // handle a post write here
                ps_async_read(); // just go back to reading
            }
            else
                delete this;
        }

    }
}<|endoftext|>


<commit_before>/**
 * @file amf.hpp
 * @author Sumedh Ghaisas
 * @author Mohan Rajendran
 * @author Ryan Curtin
 *
 * Alternating Matrix Factorization
 *
 * The AMF (alternating matrix factorization) class, from which more commonly
 * known techniques such as incremental SVD, NMF, and batch-learning SVD can be
 * derived.
 */
#ifndef __MLPACK_METHODS_AMF_AMF_HPP
#define __MLPACK_METHODS_AMF_AMF_HPP

#include <mlpack/core.hpp>

#include <mlpack/methods/amf/update_rules/nmf_mult_dist.hpp>
#include <mlpack/methods/amf/update_rules/nmf_als.hpp>
#include <mlpack/methods/amf/update_rules/svd_batch_learning.hpp>
#include <mlpack/methods/amf/update_rules/svd_incomplete_incremental_learning.hpp>
#include <mlpack/methods/amf/update_rules/svd_complete_incremental_learning.hpp>

#include <mlpack/methods/amf/init_rules/random_init.hpp>

#include <mlpack/methods/amf/termination_policies/simple_residue_termination.hpp>
#include <mlpack/methods/amf/termination_policies/simple_tolerance_termination.hpp>

namespace mlpack {
namespace amf /** Alternating Matrix Factorization **/ {

/**
 * This class implements AMF (alternating matrix factorization) on the given
 * matrix V. Alternating matrix factorization decomposes V in the form
 * \f$ V \approx WH \f$ where W is called the basis matrix and H is called the
 * encoding matrix. V is taken to be of size n x m and the obtained W is n x r
 * and H is r x m. The size r is called the rank of the factorization.
 *
 * The implementation requires three template types; the first contains the
 * policy used to determine when the algorithm has converged; the second
 * contains the initialization rule for the W and H matrix; the last contains
 * the update rule to be used during each iteration. This templatization allows
 * the user to try various update rules, initialization rules, and termination
 * policies (including ones not supplied with MLPACK) for factorization.  By
 * default, the template parameters to AMF implement non-negative matrix
 * factorization with the multiplicative distance update.
 *
 * A simple example of how to run AMF (or NMF) is shown below.
 *
 * @code
 * extern arma::mat V; // Matrix that we want to perform LMF on.
 * size_t r = 10; // Rank of decomposition
 * arma::mat W; // Basis matrix
 * arma::mat H; // Encoding matrix
 *
 * AMF<> amf; // Default options: NMF with multiplicative distance update rules.
 * amf.Apply(V, W, H, r);
 * @endcode
 *
 * @tparam TerminationPolicy The policy to use for determining when the
 *     factorization has converged.
 * @tparam InitializationRule The initialization rule for initializing W and H
 *     matrix.
 * @tparam UpdateRule The update rule for calculating W and H matrix at each
 *     iteration.
 *
 * @see NMFMultiplicativeDistanceUpdate, SimpleResidueTermination
 */
template<typename TerminationPolicyType = SimpleResidueTermination,
         typename InitializationRuleType = RandomInitialization,
         typename UpdateRuleType = NMFMultiplicativeDistanceUpdate>
class AMF
{
 public:
  /**
   * Create the AMF object and (optionally) set the parameters which AMF will
   * run with.  The minimum residue refers to the root mean square of the
   * difference between two subsequent iterations of the product W * H.  A low
   * residue indicates that subsequent iterations are not producing much change
   * in W and H.  Once the residue goes below the specified minimum residue, the
   * algorithm terminates.
   *
   * @param initializationRule Optional instantiated InitializationRule object
   *      for initializing the W and H matrices.
   * @param updateRule Optional instantiated UpdateRule object; this parameter
   *      is useful when the update rule for the W and H vector has state that
   *      it needs to store (i.e. HUpdate() and WUpdate() are not static
   *      functions).
   * @param terminationPolicy Optional instantiated TerminationPolicy object.
   */
  AMF(const TerminationPolicyType& terminationPolicy = TerminationPolicyType(),
      const InitializationRuleType& initializeRule = InitializationRuleType(),
      const UpdateRuleType& update = UpdateRuleType());

  /**
   * Apply Alternating Matrix Factorization to the provided matrix.
   *
   * @param V Input matrix to be factorized.
   * @param W Basis matrix to be output.
   * @param H Encoding matrix to output.
   * @param r Rank r of the factorization.
   */
  template<typename MatType>
  double Apply(const MatType& V,
               const size_t r,
               arma::mat& W,
               arma::mat& H);

  //! Access the termination policy.
  const TerminationPolicyType& TerminationPolicy() const
  { return terminationPolicy; }
  //! Modify the termination policy.
  TerminationPolicyType& TerminationPolicy() { return terminationPolicy; }

  //! Access the initialization rule.
  const InitializationRuleType& InitializeRule() const
  { return initializationRule; }
  //! Modify the initialization rule.
  InitializationRuleType& InitializeRule() { return initializationRule; }

  //! Access the update rule.
  const UpdateRuleType& Update() const { return update; }
  //! Modify the update rule.
  UpdateRuleType& Update() { return update; }

 private:
  //! Termination policy.
  TerminationPolicyType terminationPolicy;
  //! Instantiated initialization Rule.
  InitializationRuleType initializationRule;
  //! Instantiated update rule.
  UpdateRuleType update;
}; // class AMF

typedef amf::AMF<amf::SimpleResidueTermination,
                 amf::RandomInitialization,
                 amf::NMFALSUpdate> NMFALSFactorizer;

//! Add simple typedefs
#ifdef MLPACK_USE_CXX11

/**
 * SVDBatchFactorizer factorizes given matrix V into two matrices W and H by
 * gradient descent. SVD batch learning is described in paper 'A Guide to
 * singular Value Decomposition' by Chih-Chao Ma.
 *
 * @see SVDBatchLearning
 */
template<class MatType>
using SVDBatchFactorizer = amf::AMF<amf::SimpleToleranceTermination<MatType>,
                                    amf::RandomInitialization,
                                    amf::SVDBatchLearning>;

/**
 * SVDIncompleteIncrementalFactorizer factorizes given matrix V into two matrices
 * W and H by incomplete incremental gradient descent. SVD incomplete incremental
 * learning is described in paper 'A Guide to singular Value Decomposition'
 * by Chih-Chao Ma.
 *
 * @see SVDIncompleteIncrementalLearning
 */
template<class MatType>
using SVDIncompleteIncrementalFactorizer = amf::AMF<amf::SimpleToleranceTermination<MatType>,
                                                    amf::RandomInitialization,
                                                    amf::SVDIncompleteIncrementalLearning>;
/**
 * SVDCompleteIncrementalFactorizer factorizes given matrix V into two matrices
 * W and H by complete incremental gradient descent. SVD complete incremental
 * learning is described in paper 'A Guide to singular Value Decomposition'
 * by Chih-Chao Ma.
 *
 * @see SVDCompleteIncrementalLearning
 */
template<class MatType>
using SVDCompleteIncrementalFactorizer = amf::AMF<amf::SimpleToleranceTermination<MatType>,
                                                  amf::RandomInitialization,
                                                  amf::SVDCompleteIncrementalLearning<MatType> >;

#else // #ifdef MLPACK_USE_CXX11

/**
 * SparseSVDBatchFactorizer factorizes given sparse matrix V into two matrices
 * W and H by gradient descent. SVD batch learning is described in paper 'A Guide to
 * singular Value Decomposition' by Chih-Chao Ma.
 *
 * @see SVDBatchLearning
 */
typedef amf::AMF<amf::SimpleToleranceTermination<arma::sp_mat>,
                 amf::RandomInitialization,
                 amf::SVDBatchLearning> SparseSVDBatchFactorizer;

/**
 * SparseSVDBatchFactorizer factorizes given matrix V into two matrices
 * W and H by gradient descent. SVD batch learning is described in paper 'A Guide to
 * singular Value Decomposition' by Chih-Chao Ma.
 *
 * @see SVDBatchLearning
 */
typedef amf::AMF<amf::SimpleToleranceTermination<arma::mat>,
                 amf::RandomInitialization,
                 amf::SVDBatchLearning> SVDBatchFactorizer;
/**
 * SparseSVDIncompleteIncrementalFactorizer factorizes given sparse matrix V
 * into two matrices W and H by incomplete incremental gradient descent.
 * SVD incomplete incremental learning is described in paper 'A Guide to singular
 * Value Decomposition' by Chih-Chao Ma.
 *
 * @see SVDIncompleteIncrementalLearning
 */
typedef amf::AMF<amf::SimpleToleranceTermination<arma::sp_mat>,
                 amf::RandomInitialization,
                 amf::SVDIncompleteIncrementalLearning>
        SparseSVDIncompleteIncrementalFactorizer;

/**
 * SVDIncompleteIncrementalFactorizer factorizes given matrix V into two matrices
 * W and H by incomplete incremental gradient descent. SVD incomplete incremental
 * learning is described in paper 'A Guide to singular Value Decomposition'
 * by Chih-Chao Ma.
 *
 * @see SVDIncompleteIncrementalLearning
 */
typedef amf::AMF<amf::SimpleToleranceTermination<arma::mat>,
                 amf::RandomInitialization,
                 amf::SVDIncompleteIncrementalLearning>
        SVDIncompleteIncrementalFactorizer;

/**
 * SparseSVDCompleteIncrementalFactorizer factorizes given sparse matrix V
 * into two matrices W and H by complete incremental gradient descent. SVD
 * complete incremental learning is described in paper 'A Guide to singular
 * Value Decomposition' by Chih-Chao Ma.
 *
 * @see SVDCompleteIncrementalLearning
 */
typedef amf::AMF<amf::SimpleToleranceTermination<arma::sp_mat>,
                 amf::RandomInitialization,
                 amf::SVDCompleteIncrementalLearning<arma::sp_mat> >
        SparseSVDCompleteIncrementalFactorizer;

/**
 * SVDCompleteIncrementalFactorizer factorizes given matrix V into two matrices
 * W and H by complete incremental gradient descent. SVD complete incremental
 * learning is described in paper 'A Guide to singular Value Decomposition'
 * by Chih-Chao Ma.
 *
 * @see SVDCompleteIncrementalLearning
 */
typedef amf::AMF<amf::SimpleToleranceTermination<arma::mat>,
                 amf::RandomInitialization,
                 amf::SVDCompleteIncrementalLearning<arma::mat> >
        SVDCompleteIncrementalFactorizer;

#endif // #ifdef MLPACK_USE_CXX11

}; // namespace amf
}; // namespace mlpack

// Include implementation.
#include "amf_impl.hpp"

#endif // __MLPACK_METHODS_AMF_AMF_HPP

<commit_msg>Fix documentation; thanks to Kumar.<commit_after>/**
 * @file amf.hpp
 * @author Sumedh Ghaisas
 * @author Mohan Rajendran
 * @author Ryan Curtin
 *
 * Alternating Matrix Factorization
 *
 * The AMF (alternating matrix factorization) class, from which more commonly
 * known techniques such as incremental SVD, NMF, and batch-learning SVD can be
 * derived.
 */
#ifndef __MLPACK_METHODS_AMF_AMF_HPP
#define __MLPACK_METHODS_AMF_AMF_HPP

#include <mlpack/core.hpp>

#include <mlpack/methods/amf/update_rules/nmf_mult_dist.hpp>
#include <mlpack/methods/amf/update_rules/nmf_als.hpp>
#include <mlpack/methods/amf/update_rules/svd_batch_learning.hpp>
#include <mlpack/methods/amf/update_rules/svd_incomplete_incremental_learning.hpp>
#include <mlpack/methods/amf/update_rules/svd_complete_incremental_learning.hpp>

#include <mlpack/methods/amf/init_rules/random_init.hpp>

#include <mlpack/methods/amf/termination_policies/simple_residue_termination.hpp>
#include <mlpack/methods/amf/termination_policies/simple_tolerance_termination.hpp>

namespace mlpack {
namespace amf /** Alternating Matrix Factorization **/ {

/**
 * This class implements AMF (alternating matrix factorization) on the given
 * matrix V. Alternating matrix factorization decomposes V in the form
 * \f$ V \approx WH \f$ where W is called the basis matrix and H is called the
 * encoding matrix. V is taken to be of size n x m and the obtained W is n x r
 * and H is r x m. The size r is called the rank of the factorization.
 *
 * The implementation requires three template types; the first contains the
 * policy used to determine when the algorithm has converged; the second
 * contains the initialization rule for the W and H matrix; the last contains
 * the update rule to be used during each iteration. This templatization allows
 * the user to try various update rules, initialization rules, and termination
 * policies (including ones not supplied with MLPACK) for factorization.  By
 * default, the template parameters to AMF implement non-negative matrix
 * factorization with the multiplicative distance update.
 *
 * A simple example of how to run AMF (or NMF) is shown below.
 *
 * @code
 * extern arma::mat V; // Matrix that we want to perform LMF on.
 * size_t r = 10; // Rank of decomposition
 * arma::mat W; // Basis matrix
 * arma::mat H; // Encoding matrix
 *
 * AMF<> amf; // Default options: NMF with multiplicative distance update rules.
 * amf.Apply(V, r, W, H);
 * @endcode
 *
 * @tparam TerminationPolicy The policy to use for determining when the
 *     factorization has converged.
 * @tparam InitializationRule The initialization rule for initializing W and H
 *     matrix.
 * @tparam UpdateRule The update rule for calculating W and H matrix at each
 *     iteration.
 *
 * @see NMFMultiplicativeDistanceUpdate, SimpleResidueTermination
 */
template<typename TerminationPolicyType = SimpleResidueTermination,
         typename InitializationRuleType = RandomInitialization,
         typename UpdateRuleType = NMFMultiplicativeDistanceUpdate>
class AMF
{
 public:
  /**
   * Create the AMF object and (optionally) set the parameters which AMF will
   * run with.  The minimum residue refers to the root mean square of the
   * difference between two subsequent iterations of the product W * H.  A low
   * residue indicates that subsequent iterations are not producing much change
   * in W and H.  Once the residue goes below the specified minimum residue, the
   * algorithm terminates.
   *
   * @param initializationRule Optional instantiated InitializationRule object
   *      for initializing the W and H matrices.
   * @param updateRule Optional instantiated UpdateRule object; this parameter
   *      is useful when the update rule for the W and H vector has state that
   *      it needs to store (i.e. HUpdate() and WUpdate() are not static
   *      functions).
   * @param terminationPolicy Optional instantiated TerminationPolicy object.
   */
  AMF(const TerminationPolicyType& terminationPolicy = TerminationPolicyType(),
      const InitializationRuleType& initializeRule = InitializationRuleType(),
      const UpdateRuleType& update = UpdateRuleType());

  /**
   * Apply Alternating Matrix Factorization to the provided matrix.
   *
   * @param V Input matrix to be factorized.
   * @param W Basis matrix to be output.
   * @param H Encoding matrix to output.
   * @param r Rank r of the factorization.
   */
  template<typename MatType>
  double Apply(const MatType& V,
               const size_t r,
               arma::mat& W,
               arma::mat& H);

  //! Access the termination policy.
  const TerminationPolicyType& TerminationPolicy() const
  { return terminationPolicy; }
  //! Modify the termination policy.
  TerminationPolicyType& TerminationPolicy() { return terminationPolicy; }

  //! Access the initialization rule.
  const InitializationRuleType& InitializeRule() const
  { return initializationRule; }
  //! Modify the initialization rule.
  InitializationRuleType& InitializeRule() { return initializationRule; }

  //! Access the update rule.
  const UpdateRuleType& Update() const { return update; }
  //! Modify the update rule.
  UpdateRuleType& Update() { return update; }

 private:
  //! Termination policy.
  TerminationPolicyType terminationPolicy;
  //! Instantiated initialization Rule.
  InitializationRuleType initializationRule;
  //! Instantiated update rule.
  UpdateRuleType update;
}; // class AMF

typedef amf::AMF<amf::SimpleResidueTermination,
                 amf::RandomInitialization,
                 amf::NMFALSUpdate> NMFALSFactorizer;

//! Add simple typedefs
#ifdef MLPACK_USE_CXX11

/**
 * SVDBatchFactorizer factorizes given matrix V into two matrices W and H by
 * gradient descent. SVD batch learning is described in paper 'A Guide to
 * singular Value Decomposition' by Chih-Chao Ma.
 *
 * @see SVDBatchLearning
 */
template<class MatType>
using SVDBatchFactorizer = amf::AMF<amf::SimpleToleranceTermination<MatType>,
                                    amf::RandomInitialization,
                                    amf::SVDBatchLearning>;

/**
 * SVDIncompleteIncrementalFactorizer factorizes given matrix V into two matrices
 * W and H by incomplete incremental gradient descent. SVD incomplete incremental
 * learning is described in paper 'A Guide to singular Value Decomposition'
 * by Chih-Chao Ma.
 *
 * @see SVDIncompleteIncrementalLearning
 */
template<class MatType>
using SVDIncompleteIncrementalFactorizer = amf::AMF<amf::SimpleToleranceTermination<MatType>,
                                                    amf::RandomInitialization,
                                                    amf::SVDIncompleteIncrementalLearning>;
/**
 * SVDCompleteIncrementalFactorizer factorizes given matrix V into two matrices
 * W and H by complete incremental gradient descent. SVD complete incremental
 * learning is described in paper 'A Guide to singular Value Decomposition'
 * by Chih-Chao Ma.
 *
 * @see SVDCompleteIncrementalLearning
 */
template<class MatType>
using SVDCompleteIncrementalFactorizer = amf::AMF<amf::SimpleToleranceTermination<MatType>,
                                                  amf::RandomInitialization,
                                                  amf::SVDCompleteIncrementalLearning<MatType> >;

#else // #ifdef MLPACK_USE_CXX11

/**
 * SparseSVDBatchFactorizer factorizes given sparse matrix V into two matrices
 * W and H by gradient descent. SVD batch learning is described in paper 'A Guide to
 * singular Value Decomposition' by Chih-Chao Ma.
 *
 * @see SVDBatchLearning
 */
typedef amf::AMF<amf::SimpleToleranceTermination<arma::sp_mat>,
                 amf::RandomInitialization,
                 amf::SVDBatchLearning> SparseSVDBatchFactorizer;

/**
 * SparseSVDBatchFactorizer factorizes given matrix V into two matrices
 * W and H by gradient descent. SVD batch learning is described in paper 'A Guide to
 * singular Value Decomposition' by Chih-Chao Ma.
 *
 * @see SVDBatchLearning
 */
typedef amf::AMF<amf::SimpleToleranceTermination<arma::mat>,
                 amf::RandomInitialization,
                 amf::SVDBatchLearning> SVDBatchFactorizer;
/**
 * SparseSVDIncompleteIncrementalFactorizer factorizes given sparse matrix V
 * into two matrices W and H by incomplete incremental gradient descent.
 * SVD incomplete incremental learning is described in paper 'A Guide to singular
 * Value Decomposition' by Chih-Chao Ma.
 *
 * @see SVDIncompleteIncrementalLearning
 */
typedef amf::AMF<amf::SimpleToleranceTermination<arma::sp_mat>,
                 amf::RandomInitialization,
                 amf::SVDIncompleteIncrementalLearning>
        SparseSVDIncompleteIncrementalFactorizer;

/**
 * SVDIncompleteIncrementalFactorizer factorizes given matrix V into two matrices
 * W and H by incomplete incremental gradient descent. SVD incomplete incremental
 * learning is described in paper 'A Guide to singular Value Decomposition'
 * by Chih-Chao Ma.
 *
 * @see SVDIncompleteIncrementalLearning
 */
typedef amf::AMF<amf::SimpleToleranceTermination<arma::mat>,
                 amf::RandomInitialization,
                 amf::SVDIncompleteIncrementalLearning>
        SVDIncompleteIncrementalFactorizer;

/**
 * SparseSVDCompleteIncrementalFactorizer factorizes given sparse matrix V
 * into two matrices W and H by complete incremental gradient descent. SVD
 * complete incremental learning is described in paper 'A Guide to singular
 * Value Decomposition' by Chih-Chao Ma.
 *
 * @see SVDCompleteIncrementalLearning
 */
typedef amf::AMF<amf::SimpleToleranceTermination<arma::sp_mat>,
                 amf::RandomInitialization,
                 amf::SVDCompleteIncrementalLearning<arma::sp_mat> >
        SparseSVDCompleteIncrementalFactorizer;

/**
 * SVDCompleteIncrementalFactorizer factorizes given matrix V into two matrices
 * W and H by complete incremental gradient descent. SVD complete incremental
 * learning is described in paper 'A Guide to singular Value Decomposition'
 * by Chih-Chao Ma.
 *
 * @see SVDCompleteIncrementalLearning
 */
typedef amf::AMF<amf::SimpleToleranceTermination<arma::mat>,
                 amf::RandomInitialization,
                 amf::SVDCompleteIncrementalLearning<arma::mat> >
        SVDCompleteIncrementalFactorizer;

#endif // #ifdef MLPACK_USE_CXX11

}; // namespace amf
}; // namespace mlpack

// Include implementation.
#include "amf_impl.hpp"

#endif // __MLPACK_METHODS_AMF_AMF_HPP

<|endoftext|>


<commit_before>/*-------------brownian.cpp---------------------------------------------------//
*
*              What Color is BROWNian Motion?
*
* Purpose: This will be a simple Brownian motion simulation. I will throw the
*          results into vbots and get out some 3-d motion and such.
*
*          I will then do some Doppler shift stuff to see how the color changes
*          based on the velocity of the initial particles (assuming they are
*          emitting light and are moving relatively fast).
*
*   State: Currently adding in the hard_sphere collisions. Woo!
*
*   Notes: I should massacre the vbots code and stick it into this by imbedding
*          python into c++ code. This is somewhat documented online. This would
*          mean that I could generate a series of png files rather than output
*          files in the end, saving a good bit or writing time and space.
*
*-----------------------------------------------------------------------------*/

#include <iostream>
#include <vector>
#include <stdlib.h>
#include <time.h>

using namespace std;

/*----------------------------------------------------------------------------//
* STRUCTURES AND FUNCTIONS
*-----------------------------------------------------------------------------*/

struct part{
    double radius, mass, x, y, z, vx, vy, vz;             // Particle parameters
};

struct vox_cube{
    double x, y, z, intensity;
};

vector<part> simulate(double cube_length, vector<part> particles, int max_time,
                      double box_length, double timestep);
vector<vox_cube> dopper(vector<part> particles);
vector<part> fill_box(int pnum, double cube_length, double max_vel, double r1,
                      double r2, double mass_1, double mass_2);
vector <part> hard_sphere(part part_1, part part_2);

/*----------------------------------------------------------------------------//
* MAIN
*-----------------------------------------------------------------------------*/

int main(){

    vector<part> particles = fill_box(40, 40, 40, 1, 5, 0.5, 0.5);
}

/*----------------------------------------------------------------------------//
* SUBROUTINES
*-----------------------------------------------------------------------------*/

// Function to fill the box with randomly positioned initial particles. Note
// that I should be using random velocities too.
vector<part> fill_box(int pnum, double cube_length, double max_vel, double r1,
                      double r2, double mass_1, double mass_2){

    srand(time(0));
    vector<part> particles;
    part particle;

    // Let's go ahead and set the large particle in the middle
    particle.x = rand() % 10000 * 0.0001 * cube_length;
    particle.y = rand() % 10000 * 0.0001 * cube_length;
    particle.z = rand() % 10000 * 0.0001 * cube_length;
    particle.vx = rand() % 10000 * 0.0001 * max_vel;
    particle.vy = rand() % 10000 * 0.0001 * max_vel;
    particle.vz = rand() % 10000 * 0.0001 * max_vel;
    particle.radius = r2;
    particle.mass = mass_2;

    particles.push_back(particle);

    // Random number generator
    for (int i= 0; i <= pnum; i++){

        particle.x = rand() % 10000 * 0.0001 * cube_length;
            while (particle.x > (particles[0].x - r2) &&
                   particle.x < (particles[0].x + r2)){
                particle.x = rand() % 10000 * 0.0001 * cube_length;
                cout << "check " << i + 1 << endl;
            }

        particle.y = rand() % 10000 * 0.0001 * cube_length;
            while (particle.y > particles[0].y - r2 &&
                   particle.y < particles[0].y + r2){
                particle.y = rand() % 10000 * 0.0001 * cube_length;
            }

        particle.z = rand() % 10000 * 0.0001 * cube_length;
            while (particle.z > particles[0].z - r2 &&
                   particle.z < particles[0].z + r2){
                particle.z = rand() % 10000 * 0.0001 * cube_length;
            }

        particle.vx = rand() % 10000 * 0.0001 * max_vel;
        particle.vy = rand() % 10000 * 0.0001 * max_vel;
        particle.vz = rand() % 10000 * 0.0001 * max_vel;
        particle.radius = r1;
        particle.mass = mass_2;

        particles.push_back(particle);

    }

    for (int i = 0; i < particles.size(); i++){
        cout << i << '\t' << particles[i].x << endl;
    }

    return particles;
}

// This should deal with the interactions of the partiocles.
vector<part> simulate(double cube_length, vector<part> particles, int max_time,
                      double box_length, double timestep){

    // We will certainly have to do a hard sphere collision if any two particles
    // become sufficiently close to each other. We should go ahead and add in
    // a vector of parts...
    vector<part> collision_out;
    part particle;

    particle.x = 0;
    particle.y = 0;
    particle.z = 0;
    particle.vx = 0;
    particle.vy = 0;
    particle.vz = 0;
    particle.radius = 0;
    particle.mass = 0;

    collision_out.push_back(particle);
    collision_out.push_back(particle);

    // So let's start by moving all the particles forward a single timestep
    for (int i = 0; i < max_time; i++){
        for (int ii = 0; ii < particles.size(); ii++){
            particles[ii].x = particles[ii].vx * timestep;
            if (particles[ii].x > box_length){
                particles[ii].x -= box_length;
            }

            if (particles[ii].x < 0){
                particles[ii].x += box_length;
            }

            particles[ii].y = particles[ii].vy * timestep;
            if (particles[ii].y > box_length){
                particles[ii].y -= box_length;
            }

            if (particles[ii].y < 0){
                particles[ii].y += box_length;
            }

            particles[ii].z = particles[ii].vz * timestep;
            if (particles[ii].z > box_length){
                particles[ii].z -= box_length;
            }

            if (particles[ii].z < 0){
                particles[ii].z += box_length;
            }

            // I really don't like all these nested loops...
            for (int iii = 0; iii < particles.size(); iii++){
                if (particles[ii].x > (particles[iii].x -
                                       particles[iii].radius) &&
                    particles[ii].y > (particles[iii].y -
                                       particles[iii].radius) &&
                    particles[ii].z > (particles[iii].z -
                                       particles[iii].radius) &&
                    particles[ii].x < (particles[iii].x +
                                       particles[iii].radius) &&
                    particles[ii].y < (particles[iii].y +
                                       particles[iii].radius) &&
                    particles[ii].z < (particles[iii].z +
                                       particles[iii].radius)){

                    collision_out = hard_sphere(particles[ii], particles[iii]);
                }
            }

        }
    }
}

// UNFINISHED!!!
// I may need to perform a "hard sphere collision" if the smaller particle is
// within the radius of the larger particle. I think I'll assume that the radius
// of the smaller particle is sufficiently small that I don't have to worry
// about it. I will also assume that the larger particle's radius will fluctuate
// by an amount that varies with the timestep such that it will "catch" all the
// particles after they have already pierced the shell.
vector<part> hard_sphere(part part_1, part part_2){

    // Creating the solutions vector
    vector<part> collision_out;

    vector <part> soln;

    part particle;

    particle.x = 0;
    particle.y = 0;
    particle.z = 0;
    particle.vx = 0;
    particle.vy = 0;
    particle.vz = 0;
    particle.radius = 0;
    particle.mass = 0;

    soln.push_back(particle);
    soln.push_back(particle);

    // This is a time-driven simulation, we will need to define a global
    // variable to ultimately find the final velocity.

    double del_vx = part_2.vx - part_1.vx;
    double del_vy = part_2.vy - part_1.vy;
    double del_vz = part_2.vz - part_1.vz;
    double del_x = part_2.x - part_1.x;
    double del_y = part_2.y - part_1.y;
    double del_z = part_2.z - part_1.z;
    double sigma = part_1.radius + part_2.radius;

    double J = (2 * part_1.mass * part_2.mass *
               ((del_vx * del_x) + (del_vy * del_y) + (del_vz * del_z)) /
               (sigma * (part_1.mass + part_2.mass)));

    soln[0].vx = part_1.vx + (J * del_x) / (sigma * part_1.mass);
    soln[0].vy = part_1.vy + (J * del_y) / (sigma * part_1.mass);
    soln[0].vz = part_1.vz + (J * del_z) / (sigma * part_1.mass);
    soln[1].vx = part_2.vx + (J * del_x) / (sigma * part_2.mass);
    soln[1].vy = part_2.vy + (J * del_y) / (sigma * part_2.mass);
    soln[1].vz = part_2.vz + (J * del_z) / (sigma * part_2.mass);

    soln[0].mass = part_1.mass;
    soln[0].radius = part_1.radius;
    soln[1].mass = part_2.mass;
    soln[1].radius = part_2.radius;

    return soln;
}

// The doppler shift stuff will return a 64 X 64 X 64 grid of voxels to use.
// This will have to be written to a file to be used by vbots.
vector<vox_cube> dopper(vector<part> particles){
}
<commit_msg>Forgot to add in the change in position due to the collision.<commit_after>/*-------------brownian.cpp---------------------------------------------------//
*
*              What Color is BROWNian Motion?
*
* Purpose: This will be a simple Brownian motion simulation. I will throw the
*          results into vbots and get out some 3-d motion and such.
*
*          I will then do some Doppler shift stuff to see how the color changes
*          based on the velocity of the initial particles (assuming they are
*          emitting light and are moving relatively fast).
*
*   State: Currently adding in the hard_sphere collisions. Woo!
*
*   Notes: I should massacre the vbots code and stick it into this by imbedding
*          python into c++ code. This is somewhat documented online. This would
*          mean that I could generate a series of png files rather than output
*          files in the end, saving a good bit or writing time and space.
*
*-----------------------------------------------------------------------------*/

#include <iostream>
#include <vector>
#include <stdlib.h>
#include <time.h>

using namespace std;

/*----------------------------------------------------------------------------//
* STRUCTURES AND FUNCTIONS
*-----------------------------------------------------------------------------*/

struct part{
    double radius, mass, x, y, z, vx, vy, vz;             // Particle parameters
};

struct vox_cube{
    double x, y, z, intensity;
};

vector<part> simulate(double cube_length, vector<part> particles, int max_time,
                      double box_length, double timestep);
vector<vox_cube> dopper(vector<part> particles);
vector<part> fill_box(int pnum, double cube_length, double max_vel, double r1,
                      double r2, double mass_1, double mass_2);
vector <part> hard_sphere(part part_1, part part_2, double timestep);

/*----------------------------------------------------------------------------//
* MAIN
*-----------------------------------------------------------------------------*/

int main(){

    vector<part> particles = fill_box(40, 40, 40, 1, 5, 0.5, 0.5);
}

/*----------------------------------------------------------------------------//
* SUBROUTINES
*-----------------------------------------------------------------------------*/

// Function to fill the box with randomly positioned initial particles. Note
// that I should be using random velocities too.
vector<part> fill_box(int pnum, double cube_length, double max_vel, double r1,
                      double r2, double mass_1, double mass_2){

    srand(time(0));
    vector<part> particles;
    part particle;

    // Let's go ahead and set the large particle in the middle
    particle.x = rand() % 10000 * 0.0001 * cube_length;
    particle.y = rand() % 10000 * 0.0001 * cube_length;
    particle.z = rand() % 10000 * 0.0001 * cube_length;
    particle.vx = rand() % 10000 * 0.0001 * max_vel;
    particle.vy = rand() % 10000 * 0.0001 * max_vel;
    particle.vz = rand() % 10000 * 0.0001 * max_vel;
    particle.radius = r2;
    particle.mass = mass_2;

    particles.push_back(particle);

    // Random number generator
    for (int i= 0; i <= pnum; i++){

        particle.x = rand() % 10000 * 0.0001 * cube_length;
            while (particle.x > (particles[0].x - r2) &&
                   particle.x < (particles[0].x + r2)){
                particle.x = rand() % 10000 * 0.0001 * cube_length;
                cout << "check " << i + 1 << endl;
            }

        particle.y = rand() % 10000 * 0.0001 * cube_length;
            while (particle.y > particles[0].y - r2 &&
                   particle.y < particles[0].y + r2){
                particle.y = rand() % 10000 * 0.0001 * cube_length;
            }

        particle.z = rand() % 10000 * 0.0001 * cube_length;
            while (particle.z > particles[0].z - r2 &&
                   particle.z < particles[0].z + r2){
                particle.z = rand() % 10000 * 0.0001 * cube_length;
            }

        particle.vx = rand() % 10000 * 0.0001 * max_vel;
        particle.vy = rand() % 10000 * 0.0001 * max_vel;
        particle.vz = rand() % 10000 * 0.0001 * max_vel;
        particle.radius = r1;
        particle.mass = mass_2;

        particles.push_back(particle);

    }

    for (int i = 0; i < particles.size(); i++){
        cout << i << '\t' << particles[i].x << endl;
    }

    return particles;
}

// This should deal with the interactions of the partiocles.
vector<part> simulate(double cube_length, vector<part> particles, int max_time,
                      double box_length, double timestep){

    // We will certainly have to do a hard sphere collision if any two particles
    // become sufficiently close to each other. We should go ahead and add in
    // a vector of parts...
    vector<part> collision_out;
    part particle;

    particle.x = 0;
    particle.y = 0;
    particle.z = 0;
    particle.vx = 0;
    particle.vy = 0;
    particle.vz = 0;
    particle.radius = 0;
    particle.mass = 0;

    collision_out.push_back(particle);
    collision_out.push_back(particle);

    // So let's start by moving all the particles forward a single timestep
    for (int i = 0; i < max_time; i++){
        for (int ii = 0; ii < particles.size(); ii++){
            particles[ii].x = particles[ii].vx * timestep;
            if (particles[ii].x > box_length){
                particles[ii].x -= box_length;
            }

            if (particles[ii].x < 0){
                particles[ii].x += box_length;
            }

            particles[ii].y = particles[ii].vy * timestep;
            if (particles[ii].y > box_length){
                particles[ii].y -= box_length;
            }

            if (particles[ii].y < 0){
                particles[ii].y += box_length;
            }

            particles[ii].z = particles[ii].vz * timestep;
            if (particles[ii].z > box_length){
                particles[ii].z -= box_length;
            }

            if (particles[ii].z < 0){
                particles[ii].z += box_length;
            }

            // I really don't like all these nested loops...
            for (int iii = 0; iii < particles.size(); iii++){
                if (particles[ii].x > (particles[iii].x -
                                       particles[iii].radius) &&
                    particles[ii].y > (particles[iii].y -
                                       particles[iii].radius) &&
                    particles[ii].z > (particles[iii].z -
                                       particles[iii].radius) &&
                    particles[ii].x < (particles[iii].x +
                                       particles[iii].radius) &&
                    particles[ii].y < (particles[iii].y +
                                       particles[iii].radius) &&
                    particles[ii].z < (particles[iii].z +
                                       particles[iii].radius)){

                    collision_out = hard_sphere(particles[ii], particles[iii],
                                                timestep);

                    // Now, I might have mixed these guys up. Oops.
                    particles[ii] = collision_out[0];
                    particles[iii] = collision_out[1];
                }
            }

        }
    }
}

// UNFINISHED!!!
// I may need to perform a "hard sphere collision" if the smaller particle is
// within the radius of the larger particle. I think I'll assume that the radius
// of the smaller particle is sufficiently small that I don't have to worry
// about it. I will also assume that the larger particle's radius will fluctuate
// by an amount that varies with the timestep such that it will "catch" all the
// particles after they have already pierced the shell.
vector<part> hard_sphere(part part_1, part part_2, double timestep){

    // Creating the solutions vector
    vector<part> collision_out;

    vector <part> soln;

    part particle;

    particle.x = 0;
    particle.y = 0;
    particle.z = 0;
    particle.vx = 0;
    particle.vy = 0;
    particle.vz = 0;
    particle.radius = 0;
    particle.mass = 0;

    soln.push_back(particle);
    soln.push_back(particle);

    // This is a time-driven simulation, we will need to define a global
    // variable to ultimately find the final velocity.

    double del_vx = part_2.vx - part_1.vx;
    double del_vy = part_2.vy - part_1.vy;
    double del_vz = part_2.vz - part_1.vz;
    double del_x = part_2.x - part_1.x;
    double del_y = part_2.y - part_1.y;
    double del_z = part_2.z - part_1.z;
    double sigma = part_1.radius + part_2.radius;

    double J = (2 * part_1.mass * part_2.mass *
               ((del_vx * del_x) + (del_vy * del_y) + (del_vz * del_z)) /
               (sigma * (part_1.mass + part_2.mass)));

    // Now we need to perform the collision

    soln[0].vx = part_1.vx + (J * del_x) / (sigma * part_1.mass);
    soln[0].vy = part_1.vy + (J * del_y) / (sigma * part_1.mass);
    soln[0].vz = part_1.vz + (J * del_z) / (sigma * part_1.mass);
    soln[1].vx = part_2.vx + (J * del_x) / (sigma * part_2.mass);
    soln[1].vy = part_2.vy + (J * del_y) / (sigma * part_2.mass);
    soln[1].vz = part_2.vz + (J * del_z) / (sigma * part_2.mass);

    soln[0].mass = part_1.mass;
    soln[0].radius = part_1.radius;
    soln[1].mass = part_2.mass;
    soln[1].radius = part_2.radius;

    soln[0].x = part_1.x + (soln[0].vx * timestep);
    soln[0].y = part_1.y + (soln[0].vy * timestep);
    soln[0].z = part_1.z + (soln[0].vz * timestep);
    soln[1].x = part_2.x + (soln[1].vx * timestep);
    soln[1].y = part_2.y + (soln[1].vy * timestep);
    soln[1].z = part_2.z + (soln[1].vz * timestep);

    return soln;
}

// The doppler shift stuff will return a 64 X 64 X 64 grid of voxels to use.
// This will have to be written to a file to be used by vbots.
vector<vox_cube> dopper(vector<part> particles){
}
<|endoftext|>