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

Module Name:

    func_interp.cpp

Abstract:
    See func_interp.h

Author:

    Leonardo de Moura (leonardo) 2010-12-30.

Revision History:

--*/
#include"func_interp.h"
#include"var_subst.h"
#include"obj_hashtable.h"
#include"ast_pp.h"
#include"ast_smt2_pp.h"

func_entry::func_entry(ast_manager & m, unsigned arity, expr * const * args, expr * result):
    m_args_are_values(true),
    m_result(result) {
    SASSERT(is_ground(result));
    m.inc_ref(result);
    for (unsigned i = 0; i < arity; i++) {
        expr * arg = args[i];
        SASSERT(is_ground(arg));
        if (!m.is_value(arg))
            m_args_are_values = false;
        m.inc_ref(arg);
        m_args[i] = arg;
    }
}

func_entry * func_entry::mk(ast_manager & m, unsigned arity, expr * const * args, expr * result) {
    small_object_allocator & allocator = m.get_allocator();
    unsigned sz = get_obj_size(arity);
    void * mem  = allocator.allocate(sz);
    return new (mem) func_entry(m, arity, args, result);
}

void func_entry::set_result(ast_manager & m, expr * r) {
    m.inc_ref(r);
    m.dec_ref(m_result);
    m_result = r;
}

bool func_entry::eq_args(ast_manager & m, unsigned arity, expr * const * args) const {
    unsigned i = 0;
    for (; i < arity; i++) {
        if (!m.are_equal(m_args[i], args[i]))
            return false;
    }
    return true;
}

void func_entry::deallocate(ast_manager & m, unsigned arity) {
    for (unsigned i = 0; i < arity; i++) {
        m.dec_ref(m_args[i]);
    }
    m.dec_ref(m_result);
    small_object_allocator & allocator = m.get_allocator();
    unsigned sz = get_obj_size(arity);
    allocator.deallocate(sz, this);
}

func_interp::func_interp(ast_manager & m, unsigned arity):
    m_manager(m),
    m_arity(arity),
    m_else(0),
    m_args_are_values(true),
    m_interp(0) {
}

func_interp::~func_interp() {
    ptr_vector<func_entry>::iterator it  = m_entries.begin();
    ptr_vector<func_entry>::iterator end = m_entries.end();
    for (; it != end; ++it) {
        func_entry * curr = *it;
        curr->deallocate(m_manager, m_arity);
    }
    m_manager.dec_ref(m_else);
    m_manager.dec_ref(m_interp);
}

func_interp * func_interp::copy() const {
    func_interp * new_fi = alloc(func_interp, m_manager, m_arity);

    ptr_vector<func_entry>::const_iterator it  = m_entries.begin();
    ptr_vector<func_entry>::const_iterator end = m_entries.end();
    for (; it != end; ++it) {
        func_entry * curr = *it;
        new_fi->insert_new_entry(curr->get_args(), curr->get_result());
    }
    new_fi->set_else(m_else);
    return new_fi;
}

void func_interp::reset_interp_cache() {
    m_manager.dec_ref(m_interp);
    m_interp = 0;
}

bool func_interp::is_fi_entry_expr(expr * e, ptr_vector<expr> & args) {
    args.reset();
    if (!is_app(e) || !m().is_ite(to_app(e)))
        return false;

    app * a = to_app(e);
    expr * c = a->get_arg(0);
    expr * t = a->get_arg(1);
    expr * f = a->get_arg(2);

    if ((m_arity == 0) ||
        (m_arity == 1 && (!m().is_eq(c) || to_app(c)->get_num_args() != 2)) ||
        (m_arity > 1 && (!m().is_and(c) || to_app(c)->get_num_args() != m_arity)))
        return false;

    args.resize(m_arity, 0);
    for (unsigned i = 0; i < m_arity; i++) {
        expr * ci = (m_arity == 1 && i == 0) ? to_app(c) : to_app(c)->get_arg(i);

        if (!m().is_eq(ci) || to_app(ci)->get_num_args() != 2)
            return false;

        expr * a0 = to_app(ci)->get_arg(0);
        expr * a1 = to_app(ci)->get_arg(1);
        if (is_var(a0) && to_var(a0)->get_idx() == i)
            args[i] = a1;
        else if (is_var(a1) && to_var(a1)->get_idx() == i)
            args[i] = a0;
        else
            return false;
    }

    return true;
}

void func_interp::set_else(expr * e) {
    reset_interp_cache();
    m_manager.dec_ref(m_else);

    ptr_vector<expr> args;
    while (is_fi_entry_expr(e, args)) {
        TRACE("func_interp", tout << "fi entry expr: " << mk_ismt2_pp(e, m()) << std::endl;);
        insert_entry(args.c_ptr(), to_app(e)->get_arg(1));
        e = to_app(e)->get_arg(2);
    }

    m_manager.inc_ref(e);
    m_else = e;
}

/**
   \brief Return true if the interpretation represents the constant function.
*/
bool func_interp::is_constant() const {
    if (is_partial())
        return false;
    if (!is_ground(m_else))
        return false;
    ptr_vector<func_entry>::const_iterator it  = m_entries.begin();
    ptr_vector<func_entry>::const_iterator end = m_entries.end();
    for (; it != end; ++it) {
        func_entry * curr = *it;
        if (curr->get_result() != m_else)
            return false;
    }
    return true;
}

/**
   \brief Return a func_entry e such that m().are_equal(e.m_args[i], args[i]) for all i in [0, m_arity).
   If such entry does not exist then return 0, and store set
   args_are_values to true if for all entries e e.args_are_values() is true.
*/
func_entry * func_interp::get_entry(expr * const * args) const {
    ptr_vector<func_entry>::const_iterator it  = m_entries.begin();
    ptr_vector<func_entry>::const_iterator end = m_entries.end();
    for (; it != end; ++it) {
        func_entry * curr = *it;
        if (curr->eq_args(m(), m_arity, args))
            return curr;
    }
    return 0;
}

void func_interp::insert_entry(expr * const * args, expr * r) {
    reset_interp_cache();
    func_entry * entry = get_entry(args);
    if (entry != 0) {
        entry->set_result(m_manager, r);
        return;
    }
    insert_new_entry(args, r);
}

void func_interp::insert_new_entry(expr * const * args, expr * r) {
    reset_interp_cache();
    CTRACE("func_interp_bug", get_entry(args) != 0,
           tout << "Old: " << mk_ismt2_pp(get_entry(args)->m_result, m_manager) << "\n";
           tout << "Args:";
           for (unsigned i = 0; i < m_arity; i++) {
               tout << mk_ismt2_pp(get_entry(args)->get_arg(i), m_manager) << "\n";
           }
           tout << "New: " << mk_ismt2_pp(r, m_manager) << "\n";
           tout << "Args:";
           for (unsigned i = 0; i < m_arity; i++) {
               tout << mk_ismt2_pp(args[i], m_manager) << "\n";
           }
           tout << "Old: " << mk_ismt2_pp(get_entry(args)->get_result(), m_manager) << "\n";
           );
    SASSERT(get_entry(args) == 0);
    func_entry * new_entry = func_entry::mk(m_manager, m_arity, args, r);
    if (!new_entry->args_are_values())
        m_args_are_values = false;
    m_entries.push_back(new_entry);
}

bool func_interp::eval_else(expr * const * args, expr_ref & result) const {
    if (m_else == 0)
        return false;
    var_subst s(m_manager, false);
    SASSERT(!s.std_order()); // (VAR 0) <- args[0], (VAR 1) <- args[1], ...
    s(m_else, m_arity, args, result);
    return true;
}

/**
   \brief Return the result with the maximal number of occurrencies in m_entries.
*/
expr * func_interp::get_max_occ_result() const {
    if (m_entries.empty())
        return 0;
    obj_map<expr, unsigned> num_occs;
    expr *   r_max = 0;
    unsigned max   = 0;
    ptr_vector<func_entry>::const_iterator it  = m_entries.begin();
    ptr_vector<func_entry>::const_iterator end = m_entries.end();
    for (; it != end; ++it) {
        func_entry * curr = *it;
        expr * r = curr->get_result();
        unsigned occs = 0;
        num_occs.find(r, occs);
        occs++;
        num_occs.insert(r, occs);
        if (occs > max) {
            max   = occs;
            r_max = r;
        }
    }
    return r_max;
}

/**
   \brief Remove entries e such that e.get_result() == m_else.
*/
void func_interp::compress() {
    if (m_else == 0 || m_entries.empty())
        return; // nothing to be done
    if (!is_ground(m_else))
        return; // forall entries e in m_entries e.get_result() is ground
    unsigned i = 0;
    unsigned j = 0;
    unsigned sz = m_entries.size();
    m_args_are_values = true;
    for (; i < sz; i++) {
        func_entry * curr = m_entries[i];
        if (curr->get_result() != m_else) {
            m_entries[j] = curr;
            j++;
            if (!curr->args_are_values())
                m_args_are_values = false;
        }
        else {
            curr->deallocate(m_manager, m_arity);
        }
    }
    if (j < sz) {
        reset_interp_cache();
        m_entries.shrink(j);
    }
}

expr * func_interp::get_interp_core() const {
    if (m_else == 0)
        return 0;
    expr * r = m_else;
    ptr_buffer<expr> vars;
    ptr_vector<func_entry>::const_iterator it  = m_entries.begin();
    ptr_vector<func_entry>::const_iterator end = m_entries.end();
    for (; it != end; ++it) {
        func_entry * curr = *it;
        if (vars.empty()) {
            for (unsigned i = 0; i < m_arity; i++) {
                vars.push_back(m_manager.mk_var(i, m_manager.get_sort(curr->get_arg(i))));
            }
        }
        ptr_buffer<expr> eqs;
        for (unsigned i = 0; i < m_arity; i++) {
            eqs.push_back(m_manager.mk_eq(vars[i], curr->get_arg(i)));
        }
        SASSERT(eqs.size() == m_arity);
        expr * cond;
        if (m_arity == 1)
            cond = eqs.get(0);
        else
            cond = m_manager.mk_and(eqs.size(), eqs.c_ptr());
        r = m_manager.mk_ite(cond, curr->get_result(), r);
    }
    return r;
}

expr * func_interp::get_interp() const {
    if (m_interp != 0)
        return m_interp;
    expr * r = get_interp_core();
    if (r != 0) {
        const_cast<func_interp*>(this)->m_interp = r;
        m_manager.inc_ref(m_interp);
    }
    return r;
}

func_interp * func_interp::translate(ast_translation & translator) const {
    func_interp * new_fi = alloc(func_interp, translator.to(), m_arity);

    ptr_vector<func_entry>::const_iterator it  = m_entries.begin();
    ptr_vector<func_entry>::const_iterator end = m_entries.end();
    for (; it != end; ++it) {
        func_entry * curr = *it;
        ptr_buffer<expr> new_args;
        for (unsigned i=0; i<m_arity; i++)
            new_args.push_back(translator(curr->get_arg(i)));
        new_fi->insert_new_entry(new_args.c_ptr(), translator(curr->get_result()));
    }
    new_fi->set_else(translator(m_else));
    return new_fi;
}
<commit_msg>Bugfix for unspecified else-case in func_interps.<commit_after>/*++
Copyright (c) 2006 Microsoft Corporation

Module Name:

    func_interp.cpp

Abstract:
    See func_interp.h

Author:

    Leonardo de Moura (leonardo) 2010-12-30.

Revision History:

--*/
#include"func_interp.h"
#include"var_subst.h"
#include"obj_hashtable.h"
#include"ast_pp.h"
#include"ast_smt2_pp.h"

func_entry::func_entry(ast_manager & m, unsigned arity, expr * const * args, expr * result):
    m_args_are_values(true),
    m_result(result) {
    SASSERT(is_ground(result));
    m.inc_ref(result);
    for (unsigned i = 0; i < arity; i++) {
        expr * arg = args[i];
        SASSERT(is_ground(arg));
        if (!m.is_value(arg))
            m_args_are_values = false;
        m.inc_ref(arg);
        m_args[i] = arg;
    }
}

func_entry * func_entry::mk(ast_manager & m, unsigned arity, expr * const * args, expr * result) {
    small_object_allocator & allocator = m.get_allocator();
    unsigned sz = get_obj_size(arity);
    void * mem  = allocator.allocate(sz);
    return new (mem) func_entry(m, arity, args, result);
}

void func_entry::set_result(ast_manager & m, expr * r) {
    m.inc_ref(r);
    m.dec_ref(m_result);
    m_result = r;
}

bool func_entry::eq_args(ast_manager & m, unsigned arity, expr * const * args) const {
    unsigned i = 0;
    for (; i < arity; i++) {
        if (!m.are_equal(m_args[i], args[i]))
            return false;
    }
    return true;
}

void func_entry::deallocate(ast_manager & m, unsigned arity) {
    for (unsigned i = 0; i < arity; i++) {
        m.dec_ref(m_args[i]);
    }
    m.dec_ref(m_result);
    small_object_allocator & allocator = m.get_allocator();
    unsigned sz = get_obj_size(arity);
    allocator.deallocate(sz, this);
}

func_interp::func_interp(ast_manager & m, unsigned arity):
    m_manager(m),
    m_arity(arity),
    m_else(0),
    m_args_are_values(true),
    m_interp(0) {
}

func_interp::~func_interp() {
    ptr_vector<func_entry>::iterator it  = m_entries.begin();
    ptr_vector<func_entry>::iterator end = m_entries.end();
    for (; it != end; ++it) {
        func_entry * curr = *it;
        curr->deallocate(m_manager, m_arity);
    }
    m_manager.dec_ref(m_else);
    m_manager.dec_ref(m_interp);
}

func_interp * func_interp::copy() const {
    func_interp * new_fi = alloc(func_interp, m_manager, m_arity);

    ptr_vector<func_entry>::const_iterator it  = m_entries.begin();
    ptr_vector<func_entry>::const_iterator end = m_entries.end();
    for (; it != end; ++it) {
        func_entry * curr = *it;
        new_fi->insert_new_entry(curr->get_args(), curr->get_result());
    }
    new_fi->set_else(m_else);
    return new_fi;
}

void func_interp::reset_interp_cache() {
    m_manager.dec_ref(m_interp);
    m_interp = 0;
}

bool func_interp::is_fi_entry_expr(expr * e, ptr_vector<expr> & args) {
    args.reset();
    if (!is_app(e) || !m().is_ite(to_app(e)))
        return false;

    app * a = to_app(e);
    expr * c = a->get_arg(0);
    expr * t = a->get_arg(1);
    expr * f = a->get_arg(2);

    if ((m_arity == 0) ||
        (m_arity == 1 && (!m().is_eq(c) || to_app(c)->get_num_args() != 2)) ||
        (m_arity > 1 && (!m().is_and(c) || to_app(c)->get_num_args() != m_arity)))
        return false;

    args.resize(m_arity, 0);
    for (unsigned i = 0; i < m_arity; i++) {
        expr * ci = (m_arity == 1 && i == 0) ? to_app(c) : to_app(c)->get_arg(i);

        if (!m().is_eq(ci) || to_app(ci)->get_num_args() != 2)
            return false;

        expr * a0 = to_app(ci)->get_arg(0);
        expr * a1 = to_app(ci)->get_arg(1);
        if (is_var(a0) && to_var(a0)->get_idx() == i)
            args[i] = a1;
        else if (is_var(a1) && to_var(a1)->get_idx() == i)
            args[i] = a0;
        else
            return false;
    }

    return true;
}

void func_interp::set_else(expr * e) {
    reset_interp_cache();
    m_manager.dec_ref(m_else);

    ptr_vector<expr> args;
    while (e && is_fi_entry_expr(e, args)) {
        TRACE("func_interp", tout << "fi entry expr: " << mk_ismt2_pp(e, m()) << std::endl;);
        insert_entry(args.c_ptr(), to_app(e)->get_arg(1));
        e = to_app(e)->get_arg(2);
    }

    m_manager.inc_ref(e);
    m_else = e;
}

/**
   \brief Return true if the interpretation represents the constant function.
*/
bool func_interp::is_constant() const {
    if (is_partial())
        return false;
    if (!is_ground(m_else))
        return false;
    ptr_vector<func_entry>::const_iterator it  = m_entries.begin();
    ptr_vector<func_entry>::const_iterator end = m_entries.end();
    for (; it != end; ++it) {
        func_entry * curr = *it;
        if (curr->get_result() != m_else)
            return false;
    }
    return true;
}

/**
   \brief Return a func_entry e such that m().are_equal(e.m_args[i], args[i]) for all i in [0, m_arity).
   If such entry does not exist then return 0, and store set
   args_are_values to true if for all entries e e.args_are_values() is true.
*/
func_entry * func_interp::get_entry(expr * const * args) const {
    ptr_vector<func_entry>::const_iterator it  = m_entries.begin();
    ptr_vector<func_entry>::const_iterator end = m_entries.end();
    for (; it != end; ++it) {
        func_entry * curr = *it;
        if (curr->eq_args(m(), m_arity, args))
            return curr;
    }
    return 0;
}

void func_interp::insert_entry(expr * const * args, expr * r) {
    reset_interp_cache();
    func_entry * entry = get_entry(args);
    if (entry != 0) {
        entry->set_result(m_manager, r);
        return;
    }
    insert_new_entry(args, r);
}

void func_interp::insert_new_entry(expr * const * args, expr * r) {
    reset_interp_cache();
    CTRACE("func_interp_bug", get_entry(args) != 0,
           tout << "Old: " << mk_ismt2_pp(get_entry(args)->m_result, m_manager) << "\n";
           tout << "Args:";
           for (unsigned i = 0; i < m_arity; i++) {
               tout << mk_ismt2_pp(get_entry(args)->get_arg(i), m_manager) << "\n";
           }
           tout << "New: " << mk_ismt2_pp(r, m_manager) << "\n";
           tout << "Args:";
           for (unsigned i = 0; i < m_arity; i++) {
               tout << mk_ismt2_pp(args[i], m_manager) << "\n";
           }
           tout << "Old: " << mk_ismt2_pp(get_entry(args)->get_result(), m_manager) << "\n";
           );
    SASSERT(get_entry(args) == 0);
    func_entry * new_entry = func_entry::mk(m_manager, m_arity, args, r);
    if (!new_entry->args_are_values())
        m_args_are_values = false;
    m_entries.push_back(new_entry);
}

bool func_interp::eval_else(expr * const * args, expr_ref & result) const {
    if (m_else == 0)
        return false;
    var_subst s(m_manager, false);
    SASSERT(!s.std_order()); // (VAR 0) <- args[0], (VAR 1) <- args[1], ...
    s(m_else, m_arity, args, result);
    return true;
}

/**
   \brief Return the result with the maximal number of occurrencies in m_entries.
*/
expr * func_interp::get_max_occ_result() const {
    if (m_entries.empty())
        return 0;
    obj_map<expr, unsigned> num_occs;
    expr *   r_max = 0;
    unsigned max   = 0;
    ptr_vector<func_entry>::const_iterator it  = m_entries.begin();
    ptr_vector<func_entry>::const_iterator end = m_entries.end();
    for (; it != end; ++it) {
        func_entry * curr = *it;
        expr * r = curr->get_result();
        unsigned occs = 0;
        num_occs.find(r, occs);
        occs++;
        num_occs.insert(r, occs);
        if (occs > max) {
            max   = occs;
            r_max = r;
        }
    }
    return r_max;
}

/**
   \brief Remove entries e such that e.get_result() == m_else.
*/
void func_interp::compress() {
    if (m_else == 0 || m_entries.empty())
        return; // nothing to be done
    if (!is_ground(m_else))
        return; // forall entries e in m_entries e.get_result() is ground
    unsigned i = 0;
    unsigned j = 0;
    unsigned sz = m_entries.size();
    m_args_are_values = true;
    for (; i < sz; i++) {
        func_entry * curr = m_entries[i];
        if (curr->get_result() != m_else) {
            m_entries[j] = curr;
            j++;
            if (!curr->args_are_values())
                m_args_are_values = false;
        }
        else {
            curr->deallocate(m_manager, m_arity);
        }
    }
    if (j < sz) {
        reset_interp_cache();
        m_entries.shrink(j);
    }
}

expr * func_interp::get_interp_core() const {
    if (m_else == 0)
        return 0;
    expr * r = m_else;
    ptr_buffer<expr> vars;
    ptr_vector<func_entry>::const_iterator it  = m_entries.begin();
    ptr_vector<func_entry>::const_iterator end = m_entries.end();
    for (; it != end; ++it) {
        func_entry * curr = *it;
        if (vars.empty()) {
            for (unsigned i = 0; i < m_arity; i++) {
                vars.push_back(m_manager.mk_var(i, m_manager.get_sort(curr->get_arg(i))));
            }
        }
        ptr_buffer<expr> eqs;
        for (unsigned i = 0; i < m_arity; i++) {
            eqs.push_back(m_manager.mk_eq(vars[i], curr->get_arg(i)));
        }
        SASSERT(eqs.size() == m_arity);
        expr * cond;
        if (m_arity == 1)
            cond = eqs.get(0);
        else
            cond = m_manager.mk_and(eqs.size(), eqs.c_ptr());
        r = m_manager.mk_ite(cond, curr->get_result(), r);
    }
    return r;
}

expr * func_interp::get_interp() const {
    if (m_interp != 0)
        return m_interp;
    expr * r = get_interp_core();
    if (r != 0) {
        const_cast<func_interp*>(this)->m_interp = r;
        m_manager.inc_ref(m_interp);
    }
    return r;
}

func_interp * func_interp::translate(ast_translation & translator) const {
    func_interp * new_fi = alloc(func_interp, translator.to(), m_arity);

    ptr_vector<func_entry>::const_iterator it  = m_entries.begin();
    ptr_vector<func_entry>::const_iterator end = m_entries.end();
    for (; it != end; ++it) {
        func_entry * curr = *it;
        ptr_buffer<expr> new_args;
        for (unsigned i=0; i<m_arity; i++)
            new_args.push_back(translator(curr->get_arg(i)));
        new_fi->insert_new_entry(new_args.c_ptr(), translator(curr->get_result()));
    }
    new_fi->set_else(translator(m_else));
    return new_fi;
}
<|endoftext|>


<commit_before>// RUN: %clang_cc1 -fsyntax-only -verify -pedantic %s
struct X {
  union {
    float f3;
    double d2;
  } named;

  union {
    int i;
    float f;

    union { // expected-warning{{anonymous types declared in an anonymous union are an extension}}
      float f2;
      mutable double d;
    };
  };

  void test_unqual_references();

  struct { // expected-warning{{anonymous structs are a GNU extension}}
    int a;
    float b;
  };

  void test_unqual_references_const() const;

  mutable union { // expected-error{{anonymous union at class scope must not have a storage specifier}}
    float c1;
    double c2;
  };
};

void X::test_unqual_references() {
  i = 0;
  f = 0.0;
  f2 = f;
  d = f;
  f3 = 0; // expected-error{{use of undeclared identifier 'f3'}}
  a = 0;
}

void X::test_unqual_references_const() const {
  d = 0.0;
  f2 = 0; // expected-error{{read-only variable is not assignable}}
  a = 0; // expected-error{{read-only variable is not assignable}}
}

void test_unqual_references(X x, const X xc) {
  x.i = 0;
  x.f = 0.0;
  x.f2 = x.f;
  x.d = x.f;
  x.f3 = 0; // expected-error{{no member named 'f3'}}
  x.a = 0;

  xc.d = 0.0;
  xc.f = 0; // expected-error{{read-only variable is not assignable}}
  xc.a = 0; // expected-error{{read-only variable is not assignable}}
}

struct Redecl {
  int x; // expected-note{{previous declaration is here}}
  class y { };

  union {
    int x; // expected-error{{member of anonymous union redeclares 'x'}}
    float y;
    double z; // expected-note{{previous declaration is here}}
    double zz; // expected-note{{previous definition is here}}
  };

  int z; // expected-error{{duplicate member 'z'}}
  void zz(); // expected-error{{redefinition of 'zz' as different kind of symbol}}
};

union { // expected-error{{anonymous unions at namespace or global scope must be declared 'static'}}
  int int_val;
  float float_val;
};

static union {
  int int_val2;
  float float_val2;
};

void PR21858() {
  void int_val2();
}

void f() {
  int_val2 = 0;
  float_val2 = 0.0;
}

void g() {
  union {
    int i;
    float f2;
  };
  i = 0;
  f2 = 0.0;
}

struct BadMembers {
  union {
    struct X { }; // expected-error {{types cannot be declared in an anonymous union}}
    struct { int x; int y; } y; // expected-warning{{anonymous types declared in an anonymous union are an extension}}

    void f(); // expected-error{{functions cannot be declared in an anonymous union}}
  private: int x1; // expected-error{{anonymous union cannot contain a private data member}}
  protected: float x2; // expected-error{{anonymous union cannot contain a protected data member}}
  };
};

// <rdar://problem/6481130>
typedef union { }; // expected-warning{{typedef requires a name}}

// <rdar://problem/7562438>
typedef struct objc_module *Foo ;

typedef struct _s {
    union {
        int a;
        int Foo;
    };
} s, *ps;

// <rdar://problem/7987650>
namespace test4 {
  class A {
    struct { // expected-warning{{anonymous structs are a GNU extension}}
      int s0; // expected-note {{declared private here}}
      double s1; // expected-note {{declared private here}}
      union { // expected-warning{{anonymous types declared in an anonymous struct are an extension}}
        int su0; // expected-note {{declared private here}}
        double su1; // expected-note {{declared private here}}
      };
    };
    union {
      int u0; // expected-note {{declared private here}}
      double u1; // expected-note {{declared private here}}
      struct { // expected-warning{{anonymous structs are a GNU extension}} expected-warning{{anonymous types declared in an anonymous union are an extension}}
        int us0; // expected-note {{declared private here}}
        double us1; // expected-note {{declared private here}}
      };
    };
  };

  void test() {
    A a;
    (void) a.s0;  // expected-error {{private member}}
    (void) a.s1;  // expected-error {{private member}}
    (void) a.su0; // expected-error {{private member}}
    (void) a.su1; // expected-error {{private member}}
    (void) a.u0;  // expected-error {{private member}}
    (void) a.u1;  // expected-error {{private member}}
    (void) a.us0; // expected-error {{private member}}
    (void) a.us1; // expected-error {{private member}}
  }
}

typedef void *voidPtr;

void f2() {
    union { int **ctxPtr; void **voidPtr; };
}

void foo_PR6741() {
    union {
        char *m_a;
        int *m_b;
    };

    if(1) {
        union {
            char *m_a;
            int *m_b;
        };
    }
}

namespace PR8326 {
  template <class T>
  class Foo {
  public:
    Foo()
      : x(0)
      , y(1){
    }

  private:
    const union { // expected-warning{{anonymous union cannot be 'const'}}
      struct { // expected-warning{{anonymous structs are a GNU extension}} expected-warning{{declared in an anonymous union}}
        T x;
        T y;
      };
      T v[2];
    };
  };

  Foo<int> baz;
}

namespace PR16630 {
  struct A { union { int x; float y; }; }; // expected-note {{member is declared here}}
  struct B : private A { using A::x; } b; // expected-note 2 {{private}}
  void foo () {
    b.x = 10;
    b.y = 0; // expected-error {{cannot cast 'struct B' to its private base class 'PR16630::A'}} expected-error {{'y' is a private member of 'PR16630::A'}}
  }
}
<commit_msg>Forgot to commit this change with r223975<commit_after>// RUN: %clang_cc1 -fsyntax-only -verify -pedantic %s
struct X {
  union {
    float f3;
    double d2;
  } named;

  union {
    int i;
    float f;

    union { // expected-warning{{anonymous types declared in an anonymous union are an extension}}
      float f2;
      mutable double d;
    };
  };

  void test_unqual_references();

  struct { // expected-warning{{anonymous structs are a GNU extension}}
    int a;
    float b;
  };

  void test_unqual_references_const() const;

  mutable union { // expected-error{{anonymous union at class scope must not have a storage specifier}}
    float c1;
    double c2;
  };
};

void X::test_unqual_references() {
  i = 0;
  f = 0.0;
  f2 = f;
  d = f;
  f3 = 0; // expected-error{{use of undeclared identifier 'f3'}}
  a = 0;
}

void X::test_unqual_references_const() const {
  d = 0.0;
  f2 = 0; // expected-error{{read-only variable is not assignable}}
  a = 0; // expected-error{{read-only variable is not assignable}}
}

void test_unqual_references(X x, const X xc) {
  x.i = 0;
  x.f = 0.0;
  x.f2 = x.f;
  x.d = x.f;
  x.f3 = 0; // expected-error{{no member named 'f3'}}
  x.a = 0;

  xc.d = 0.0;
  xc.f = 0; // expected-error{{read-only variable is not assignable}}
  xc.a = 0; // expected-error{{read-only variable is not assignable}}
}

struct Redecl {
  int x; // expected-note{{previous declaration is here}}
  class y { };

  union {
    int x; // expected-error{{member of anonymous union redeclares 'x'}}
    float y;
    double z; // expected-note{{previous declaration is here}}
    double zz; // expected-note{{previous definition is here}}
  };

  int z; // expected-error{{duplicate member 'z'}}
  void zz(); // expected-error{{redefinition of 'zz' as different kind of symbol}}
};

union { // expected-error{{anonymous unions at namespace or global scope must be declared 'static'}}
  int int_val;
  float float_val;
};

static union {
  int int_val2; // expected-note{{previous definition is here}}
  float float_val2;
};

void PR21858() {
  void int_val2(); // expected-error{{redefinition of 'int_val2' as different kind of symbol}}
}

void f() {
  int_val2 = 0;
  float_val2 = 0.0;
}

void g() {
  union {
    int i;
    float f2;
  };
  i = 0;
  f2 = 0.0;
}

struct BadMembers {
  union {
    struct X { }; // expected-error {{types cannot be declared in an anonymous union}}
    struct { int x; int y; } y; // expected-warning{{anonymous types declared in an anonymous union are an extension}}

    void f(); // expected-error{{functions cannot be declared in an anonymous union}}
  private: int x1; // expected-error{{anonymous union cannot contain a private data member}}
  protected: float x2; // expected-error{{anonymous union cannot contain a protected data member}}
  };
};

// <rdar://problem/6481130>
typedef union { }; // expected-warning{{typedef requires a name}}

// <rdar://problem/7562438>
typedef struct objc_module *Foo ;

typedef struct _s {
    union {
        int a;
        int Foo;
    };
} s, *ps;

// <rdar://problem/7987650>
namespace test4 {
  class A {
    struct { // expected-warning{{anonymous structs are a GNU extension}}
      int s0; // expected-note {{declared private here}}
      double s1; // expected-note {{declared private here}}
      union { // expected-warning{{anonymous types declared in an anonymous struct are an extension}}
        int su0; // expected-note {{declared private here}}
        double su1; // expected-note {{declared private here}}
      };
    };
    union {
      int u0; // expected-note {{declared private here}}
      double u1; // expected-note {{declared private here}}
      struct { // expected-warning{{anonymous structs are a GNU extension}} expected-warning{{anonymous types declared in an anonymous union are an extension}}
        int us0; // expected-note {{declared private here}}
        double us1; // expected-note {{declared private here}}
      };
    };
  };

  void test() {
    A a;
    (void) a.s0;  // expected-error {{private member}}
    (void) a.s1;  // expected-error {{private member}}
    (void) a.su0; // expected-error {{private member}}
    (void) a.su1; // expected-error {{private member}}
    (void) a.u0;  // expected-error {{private member}}
    (void) a.u1;  // expected-error {{private member}}
    (void) a.us0; // expected-error {{private member}}
    (void) a.us1; // expected-error {{private member}}
  }
}

typedef void *voidPtr;

void f2() {
    union { int **ctxPtr; void **voidPtr; };
}

void foo_PR6741() {
    union {
        char *m_a;
        int *m_b;
    };

    if(1) {
        union {
            char *m_a;
            int *m_b;
        };
    }
}

namespace PR8326 {
  template <class T>
  class Foo {
  public:
    Foo()
      : x(0)
      , y(1){
    }

  private:
    const union { // expected-warning{{anonymous union cannot be 'const'}}
      struct { // expected-warning{{anonymous structs are a GNU extension}} expected-warning{{declared in an anonymous union}}
        T x;
        T y;
      };
      T v[2];
    };
  };

  Foo<int> baz;
}

namespace PR16630 {
  struct A { union { int x; float y; }; }; // expected-note {{member is declared here}}
  struct B : private A { using A::x; } b; // expected-note 2 {{private}}
  void foo () {
    b.x = 10;
    b.y = 0; // expected-error {{cannot cast 'struct B' to its private base class 'PR16630::A'}} expected-error {{'y' is a private member of 'PR16630::A'}}
  }
}
<|endoftext|>


<commit_before>#include <fhe/FHEContext.h>
#include <fhe/FHE.h>
#include <fhe/NumbTh.h>
#include <fhe/EncryptedArray.h>
#include <utils/FileUtils.hpp>
#include <utils/timer.hpp>
#include <algebra/NDSS.h>
#include <thread>
#include <atomic>
#include <vector>

#ifdef FHE_THREADS
long WORKER_NR = 8;
#else // ifdef FHE_THREADS
long WORKER_NR = 1;
#endif // ifdef FHE_THREAD
std::vector<MDL::EncVector>encrypt(const MDL::Matrix<long>& data,
                                   const FHEPubKey        & pk,
                                   const EncryptedArray   & ea,
                                   long                     from = 0,
                                   long                     to = 0)
{
    to = to == 0 ? data.rows() : to;
    MDL::Timer timer;
    std::vector<MDL::EncVector> ctxts(to - from, pk);
    std::vector<std::thread>    workers;
    std::atomic<size_t> counter(from);

    timer.start();

    for (long wr = 0; wr < WORKER_NR; wr++) {
        workers.push_back(std::move(std::thread([&data, &ea, &to, &from,
                                                 &counter, &ctxts]() {
            size_t next;

            while ((next = counter.fetch_add(1)) < to) {
                ctxts[next - from].pack(data[next], ea);
            }
        })));
    }

    for (auto && wr : workers) wr.join();
    timer.end();
    printf("Encrypt %ld data with %ld workers costed %f sec\n", to - from,
           WORKER_NR, timer.second());
    return ctxts;
}

MDL::EncVector mean(const std::vector<MDL::EncVector>& ctxts)
{
    std::vector<std::thread>    workers;
    std::vector<MDL::EncVector> partials(WORKER_NR, ctxts[0].getPubKey());
    std::atomic<size_t> counter(WORKER_NR);
    MDL::Timer timer;

    timer.start();

    for (long i = 0; i < WORKER_NR; i++) {
        partials[i] = ctxts[i];
        workers.push_back(std::move(std::thread([&counter, &ctxts]
                                                    (MDL::EncVector& ct) {
            size_t next;

            while ((next = counter.fetch_add(1)) < ctxts.size()) {
                ct += ctxts[next];
            }
        }, std::ref(partials[i]))));
    }

    for (auto && wr : workers) {
        wr.join();
    }

    for (long i = 1; i < WORKER_NR; i++) {
        partials[0] += partials[i];
    }
    timer.end();
    printf("Sum %zd data with %ld workers costed %f sec\n", ctxts.size(),
           WORKER_NR, timer.second());
    return partials[0];
}

MDL::EncVector squareSum(std::vector<MDL::EncVector>& ctxts)
{
    MDL::Timer timer;
    std::atomic<size_t> counter(0);
    std::vector<std::thread> workers;

    timer.start();

    for (long wr = 0; wr < WORKER_NR; wr++) {
        workers.push_back(std::move(std::thread([&ctxts, &counter]() {
            size_t next;

            while ((next = counter.fetch_add(1)) < ctxts.size()) {
                ctxts[next].square();
            }
        })));
    }

    for (auto && wr : workers) wr.join();
    auto sq_sum = mean(ctxts);
    timer.end();
    printf("Square Sum costed %f sec\n", timer.second());
    return sq_sum;
}

MDL::EncVector variance(const MDL::Matrix<long>& data,
                        const EncryptedArray   & ea,
                        const FHEPubKey        & pk)
{
    MDL::EncVector square_sum(pk), sum_square(pk);
    NTL::ZZX   N(data.rows());
    const long BATCH_SIZE = 2500;
    MDL::Timer totalTimer, encTimer, evalTimer;

    totalTimer.start();

    for (long part = 0; part *BATCH_SIZE < data.rows(); part++) {
        long from  = std::min<long>(part * BATCH_SIZE, data.rows());
        long to    = std::min<long>(from + BATCH_SIZE, data.rows());
        encTimer.start();
        auto ctxts = encrypt(data, pk, ea, from, to);
        encTimer.end();
        evalTimer.start();

        if (part > 0) {
            sum_square += mean(ctxts);
            square_sum += squareSum(ctxts);
        } else {
            sum_square = mean(ctxts);
            square_sum = squareSum(ctxts);
        }
        evalTimer.end();
    }

    evalTimer.start();
    sum_square.square();
    square_sum.multByConstant(N);
    square_sum -= sum_square;
    evalTimer.end();
    totalTimer.end();
    printf("Varaice of %zd data with %ld workers used %f(%f/%f)\n",
           data.rows(), WORKER_NR,
           totalTimer.second(),
           encTimer.second(),
           evalTimer.second());
    return square_sum;
}

MDL::EncVector average(const MDL::Matrix<long>& data,
                       const EncryptedArray &ea,
                       const FHEPubKey &pk)
{
    MDL::EncVector result(pk);
    const long BATCH_SIZE = 2500;
    MDL::Timer encTimer, evalTimer;

    for (long part = 0; part *BATCH_SIZE < data.rows(); part++) {
        long from  = std::min<long>(part * BATCH_SIZE, data.rows());
        long to    = std::min<long>(from + BATCH_SIZE, data.rows());
        encTimer.start();
        auto ctxts = encrypt(data, pk, ea, from, to);
        encTimer.end();
        evalTimer.start();
        if (part > 0) {
            result += mean(ctxts);
        } else {
            result = mean(ctxts);
        }
        evalTimer.end();
    }
    printf("Mean of %zd data with %ld workders used Enc(%f)/Eval(%f)\n",
           data.rows(), WORKER_NR, encTimer.second(), evalTimer.second());
    return result;
}

int main(int argc, char *argv[]) {
    long m, p, r, L;
    ArgMapping argmap;

    argmap.arg("m", m, "m");
    argmap.arg("L", L, "L");
    argmap.arg("p", p, "p");
    argmap.arg("r", r, "r");
    argmap.parse(argc, argv);

    FHEcontext context(m, p, r);
    buildModChain(context, L);
    FHESecKey sk(context);
    sk.GenSecKey(64);
    addSome1DMatrices(sk);
    FHEPubKey pk = sk;

    auto G = context.alMod.getFactorsOverZZ()[0];
    EncryptedArray ea(context, G);

    auto data   = load_csv("adult.data");
    auto result = load_csv("adult_result");

    // auto ctxts  = encrypt(data, pk, ea);

    // {
    //     MDL::Vector<long> ret;
    //     auto summaiton = mean(ctxts);
    //     summaiton.unpack(ret, sk, ea);
    //     std::cout << ret << std::endl;
    //     std::cout << result[0] << std::endl;
    // }

    {
        MDL::Vector<long> ret;
        auto var = variance(data, ea, pk);
        var.unpack(ret, sk, ea);
        std::cout << ret << std::endl;
        std::cout << result[1] << std::endl;
    }
    return 0;
}
<commit_msg>No need to relinearization after each multiplication.<commit_after>#include <fhe/FHEContext.h>
#include <fhe/FHE.h>
#include <fhe/NumbTh.h>
#include <fhe/EncryptedArray.h>
#include <utils/FileUtils.hpp>
#include <utils/timer.hpp>
#include <algebra/NDSS.h>
#include <thread>
#include <atomic>
#include <vector>

#ifdef FHE_THREADS
long WORKER_NR = 8;
#else // ifdef FHE_THREADS
long WORKER_NR = 1;
#endif // ifdef FHE_THREAD
std::vector<MDL::EncVector>encrypt(const MDL::Matrix<long>& data,
                                   const FHEPubKey        & pk,
                                   const EncryptedArray   & ea,
                                   long                     from = 0,
                                   long                     to = 0)
{
    to = to == 0 ? data.rows() : to;
    MDL::Timer timer;
    std::vector<MDL::EncVector> ctxts(to - from, pk);
    std::vector<std::thread>    workers;
    std::atomic<size_t> counter(from);

    timer.start();

    for (long wr = 0; wr < WORKER_NR; wr++) {
        workers.push_back(std::move(std::thread([&data, &ea, &to, &from,
                                                 &counter, &ctxts]() {
            size_t next;

            while ((next = counter.fetch_add(1)) < to) {
                ctxts[next - from].pack(data[next], ea);
            }
        })));
    }

    for (auto && wr : workers) wr.join();
    timer.end();
    //printf("Encrypt %ld data with %ld workers costed %f sec\n", to - from,
    //       WORKER_NR, timer.second());
    return ctxts;
}

MDL::EncVector mean(const std::vector<MDL::EncVector>& ctxts)
{
    std::vector<std::thread>    workers;
    std::vector<MDL::EncVector> partials(WORKER_NR, ctxts[0].getPubKey());
    std::atomic<size_t> counter(WORKER_NR);
    MDL::Timer timer;

    timer.start();

    for (long i = 0; i < WORKER_NR; i++) {
        partials[i] = ctxts[i];
        workers.push_back(std::move(std::thread([&counter, &ctxts]
                                                    (MDL::EncVector& ct) {
            size_t next;

            while ((next = counter.fetch_add(1)) < ctxts.size()) {
                ct += ctxts[next];
            }
        }, std::ref(partials[i]))));
    }

    for (auto && wr : workers) {
        wr.join();
    }

    for (long i = 1; i < WORKER_NR; i++) {
        partials[0] += partials[i];
    }
    timer.end();
    //printf("Sum %zd data with %ld workers costed %f sec\n", ctxts.size(),
    //       WORKER_NR, timer.second());
    return partials[0];
}

MDL::EncVector squareSum(std::vector<MDL::EncVector>& ctxts)
{
    MDL::Timer timer;
    std::atomic<size_t> counter(0);
    std::vector<std::thread> workers;

    timer.start();

    for (long wr = 0; wr < WORKER_NR; wr++) {
        workers.push_back(std::move(std::thread([&ctxts, &counter]() {
            size_t next;

            while ((next = counter.fetch_add(1)) < ctxts.size()) {
                //ctxts[next].square();
				ctxts[next] *= ctxts[next];
            }
        })));
    }

    for (auto && wr : workers) wr.join();
    auto sq_sum = mean(ctxts);
	sq_sum.reLinearize();
    timer.end();
    printf("Square Sum costed %f sec\n", timer.second());
    return sq_sum;
}

MDL::EncVector variance(const MDL::Matrix<long>& data,
                        const EncryptedArray   & ea,
                        const FHEPubKey        & pk)
{
    MDL::EncVector square_sum(pk), sum_square(pk);
    NTL::ZZX   N(data.rows());
    const long BATCH_SIZE = 2500;
    MDL::Timer totalTimer, encTimer, evalTimer;

    totalTimer.start();

    for (long part = 0; part *BATCH_SIZE < data.rows(); part++) {
        long from  = std::min<long>(part * BATCH_SIZE, data.rows());
        long to    = std::min<long>(from + BATCH_SIZE, data.rows());
        encTimer.start();
        auto ctxts = encrypt(data, pk, ea, from, to);
        encTimer.end();
        evalTimer.start();

        if (part > 0) {
            sum_square += mean(ctxts);
            square_sum += squareSum(ctxts);
        } else {
            sum_square = mean(ctxts);
            square_sum = squareSum(ctxts);
        }
        evalTimer.end();
		printf("%ld %f %f\n", to, encTimer.second(), evalTimer.second());
    }

    evalTimer.start();
    sum_square.square();
    square_sum.multByConstant(N);
    square_sum -= sum_square;
    evalTimer.end();
    totalTimer.end();
    printf("Varaice of %zd data with %ld workers used %f(%f/%f)\n",
           data.rows(), WORKER_NR,
           totalTimer.second(),
           encTimer.second(),
           evalTimer.second());
    return square_sum;
}

MDL::EncVector average(const MDL::Matrix<long>& data,
                       const EncryptedArray &ea,
                       const FHEPubKey &pk)
{
    MDL::EncVector result(pk);
    const long BATCH_SIZE = 2500;
    MDL::Timer encTimer, evalTimer;

    for (long part = 0; part *BATCH_SIZE < data.rows(); part++) {
        long from  = std::min<long>(part * BATCH_SIZE, data.rows());
        long to    = std::min<long>(from + BATCH_SIZE, data.rows());
        encTimer.start();
        auto ctxts = encrypt(data, pk, ea, from, to);
        encTimer.end();
        evalTimer.start();
        if (part > 0) {
            result += mean(ctxts);
        } else {
            result = mean(ctxts);
        }
        evalTimer.end();
		printf("%ld %f %f\n", to, encTimer.second(), evalTimer.second());
    }
    printf("Mean of %zd data with %ld workders used Enc(%f)/Eval(%f)\n",
           data.rows(), WORKER_NR, encTimer.second(), evalTimer.second());
    return result;
}

int main(int argc, char *argv[]) {
    long m, p, r, L;
    ArgMapping argmap;

    argmap.arg("m", m, "m");
    argmap.arg("L", L, "L");
    argmap.arg("p", p, "p");
    argmap.arg("r", r, "r");
    argmap.parse(argc, argv);

    FHEcontext context(m, p, r);
    buildModChain(context, L);
    FHESecKey sk(context);
    sk.GenSecKey(64);
    addSome1DMatrices(sk);
    FHEPubKey pk = sk;

    auto G = context.alMod.getFactorsOverZZ()[0];
    EncryptedArray ea(context, G);
	printf("slots %ld\n", ea.size());
    auto data   = load_csv("adult.data");
    auto result = load_csv("adult_result");

    // auto ctxts  = encrypt(data, pk, ea);

    // {
    //     MDL::Vector<long> ret;
    //     auto summaiton = mean(ctxts);
    //     summaiton.unpack(ret, sk, ea);
    //     std::cout << ret << std::endl;
    //     std::cout << result[0] << std::endl;
    // }

    {
        MDL::Vector<long> ret;
        auto var = variance(data, ea, pk);
        var.unpack(ret, sk, ea);
        std::cout << ret << std::endl;
        std::cout << result[1] << std::endl;
    }
    return 0;
}
<|endoftext|>


<commit_before>/*******************************************************************************
Program:   Wake Forest University - Virginia Tech CTC Software
Id:        $Id$
Language:  C++
*******************************************************************************/
/*
Feature Extraction Tool - frontend to various feature extraction methods
*/

#include <cstdlib>
#include <iostream>
using std::clog;
using std::cerr;
using std::endl;
#include <fstream>
using std::ifstream;
using std::ofstream;

#include <string>
using std::string;
#include <cctype>

// ITK includes

// CTC includes
#include "ctcConfigure.h"
#include "ctcCTCImage.h"
#include "ctcCTCImageReader.h"
#include "vul_arg.h"

// Feature extraction methods
#include "FeatureExtractionMethods.h"
#include "ctcPrincipleCurvatureExtraction.h"
#include "ctcFeatureExtraction.h"
#include "MAT4Converter.h"
#include "StringtoDouble.h"

// this is ugly, should be refactored
DBType * parsedb(const char * dbname)
{
  DBType * db = new DBType;
  EntryType e;
  string entrystr;

  ifstream thefile(dbname);
  while(thefile.good())
    {
      string field;
      getline(thefile,entrystr);
      //      clog << entrystr.c_str() << endl << endl;
      if(entrystr.size() < 5)
	continue;

      int start = 0;

      // id field
      int end = entrystr.find_first_of(',', start);
      //clog << entrystr.substr(start, end-start) << endl;
      if(end != string::npos)
	e.id = atoi(entrystr.substr(start, end-start).c_str());
      else
	throw false;

      // x  field
      start = end+1;
      end = entrystr.find_first_of(',', start);
      //clog << entrystr.substr(start, end-start) << endl;
      if(end != string::npos)
	e.x = atof(entrystr.substr(start, end-start).c_str());
      else
	throw false;

      // y  field
      start = end+1;
      end = entrystr.find_first_of(',', start);
      //clog << entrystr.substr(start, end-start) << endl;
      if(end != string::npos)
	e.y = atof(entrystr.substr(start, end-start).c_str());
      else
	throw false;

      // z field
      start = end+1;
      end = entrystr.size();
      //clog << entrystr.substr(start, end-start) << endl;
      if(start < end)
	e.z = atof(entrystr.substr(start, end-start).c_str());
      else
	throw false;

      db->push_front(e);

    }
  return db;
};

int main( int argc, char* argv[] )
{
  // parse args
  vul_arg<char const*> imgdir(0, "DICOM image dir");
  vul_arg<char const*> datainfile(0, "input volume data file", "SupineData.vtk");
  vul_arg<char const*> seginfile(0, "segmented image", "SupineSegmented.vtk");
  vul_arg<char const*> outfilename(0, "Output feature filename", "PolypCandidatesExtractedInSegfile.vtk");
  //vul_arg<char const*> pfile("-p", "polyp coordinate file", "polyps");
  //vul_arg<char const*> outfilename("-o",
		//		   "output csv file name",
		//		   "features.csv");
  vul_arg_parse(argc, argv);

  /* get paths to input/output files */
  string rawinfilename = "";
  rawinfilename.append(imgdir());
  rawinfilename.append("/");
  rawinfilename.append(datainfile());
  string seginfilename = "";
  seginfilename.append(imgdir());
  seginfilename.append("/");
  seginfilename.append(seginfile());
  string outputVTKname = "";
  outputVTKname.append(outfilename());

  // read data
  //ctc::CTCImageReader::Pointer rawreader = ctc::CTCImageReader::New();
  //rawreader->SetDirectory(string(imgdir()));
  //rawreader->SetFileName(rawinfilename);
  typedef itk::ImageFileReader< ctc::CTCImageType > RawDataReaderType;
  RawDataReaderType::Pointer rawreader = RawDataReaderType::New();
  rawreader->SetFileName(rawinfilename);

  // read segmented data
  typedef itk::ImageFileReader< ctc::BinaryImageType > SegDataReaderType;
  SegDataReaderType::Pointer segreader = SegDataReaderType::New();
  segreader->SetFileName(seginfilename);

  // invoke readers
  try
    {
      rawreader->Update();
      segreader->Update();
    }
  catch (itk::ExceptionObject &ex)
    {
      std::cout << ex << std::endl;
      return EXIT_FAILURE;
    }

  // extract the features
  typedef ctc::PrincipleCurvatureExtraction FilterType;
  FilterType::Pointer filter = FilterType::New();
  filter->SetBinaryInput(segreader->GetOutput());
  filter->SetImageInput(rawreader->GetOutput());
  std::clog << "Computing Features ...";
  try
    {
      filter->Compute();
    }
  catch (itk::ExceptionObject &ex)
    {
      std::cout << ex << std::endl;
      return EXIT_FAILURE;
    }
  std::clog << " Done." << std::endl;

  // read the polyps file

  /* Will uncomment soon */
  /*
  DBType * db;
  try
    {
      db = parsedb(pfile());
    }
  catch(bool stat)
    {
      cerr << "Error reading file " << pfile() << endl;
      return EXIT_FAILURE;
    }
  */

  /* Previous Work */
  /*
  // output
  ofstream out(outfilename());

  out << "voxelx" << ","
      << "voxely" << ","
      << "voxelz" << ","
      << "kappa1" << ","
      << "kappa2" << ","
      << "shape_index" << ","
      << "curvedness" << ","
      << "gauusian_curv" << ","
      << "mean_curv" << ","
      << "dist_to_closest" << ","
      << "id_of_closest"
      << endl;

  FilterType::FeatureSampleType::Pointer features = filter->GetOutput();
  FilterType::FeatureType f;
  DBType::iterator it;
  for(int i = 0; i < features->Size(); i++)
    {
       f = features->GetMeasurementVector(i);
       int id = 0;
       float mindist = pow(512,6);
       for(it = db->begin(); it != db->end(); ++it)
	 {
	   float dx = f[0] - it->x;
	   float dy = f[1] - it->y;
	   float dz = f[2] - it->z;
	   float dist = dx*dx + dy*dy + dz*dz;
	   if( dist < mindist)
	     {
	       mindist = dist;
	       id = it->id;
	     }
	 }
       mindist = sqrt(mindist);

       //note the si is slightly different, since I use atan2 in place of atan
       float si = 0.5 + 0.1592*atan2(f[3] + f[4], f[3] - f[4]);
       float cv = 0.6366*log(sqrt((f[3]*f[3] + f[4]*f[4])/2));
       float K = f[3]*f[4];
       float H = 0.5*(f[3] + f[4]);

       out << f[0] << ","
	   << f[1] << ","
	   << f[2] << ","
	   << f[3] << ","
	   << f[4] << ","
	   << si << ","
	   << cv << ","
	   << K << ","
	   << H << ","
	   << mindist << ","
	   << id
	   << endl;
    }
  out.close();*/

    typedef ctc::FeatureExtraction FeatureExtractionFilterType;
    FeatureExtractionFilterType::Pointer FEfilter = FeatureExtractionFilterType::New();
//  FEfilter->SetInitialFeatureVector(filter->GetOutput());

    FEfilter->SetSegmentedImageInput(segreader->GetOutput());
    FEfilter->SetRawImageInput(rawreader->GetOutput());
    FEfilter->SetOutputVTK(outputVTKname);

    /* Core of feature extraction */
    FEfilter->Analyze();

//  delete db;

  return EXIT_SUCCESS;

}
<commit_msg>Feature Extraction Program version --- 1.0.0<commit_after>/*******************************************************************************
Program:   Wake Forest University - Virginia Tech CTC Software
Id:        $Id$
Language:  C++
*******************************************************************************/
/*
Feature Extraction Tool - frontend to various feature extraction methods
*/

#include <cstdlib>
#include <iostream>
using std::clog;
using std::cerr;
using std::endl;
#include <fstream>
using std::ifstream;
using std::ofstream;

#include <string>
using std::string;
#include <cctype>

// ITK includes

// CTC includes
#include "ctcConfigure.h"
#include "ctcCTCImage.h"
#include "ctcCTCImageReader.h"
#include "vul_arg.h"

// Feature extraction methods
#include "FeatureExtractionMethods.h"
#include "ctcPrincipleCurvatureExtraction.h"
#include "ctcFeatureExtraction.h"
#include "MAT4Converter.h"
#include "StringtoDouble.h"

// this is ugly, should be refactored
DBType * parsedb(const char * dbname)
{
  DBType * db = new DBType;
  EntryType e;
  string entrystr;

  ifstream thefile(dbname);
  while(thefile.good())
    {
      string field;
      getline(thefile,entrystr);
      //      clog << entrystr.c_str() << endl << endl;
      if(entrystr.size() < 5)
	continue;

      int start = 0;

      // id field
      int end = entrystr.find_first_of(',', start);
      //clog << entrystr.substr(start, end-start) << endl;
      if(end != string::npos)
	e.id = atoi(entrystr.substr(start, end-start).c_str());
      else
	throw false;

      // x  field
      start = end+1;
      end = entrystr.find_first_of(',', start);
      //clog << entrystr.substr(start, end-start) << endl;
      if(end != string::npos)
	e.x = atof(entrystr.substr(start, end-start).c_str());
      else
	throw false;

      // y  field
      start = end+1;
      end = entrystr.find_first_of(',', start);
      //clog << entrystr.substr(start, end-start) << endl;
      if(end != string::npos)
	e.y = atof(entrystr.substr(start, end-start).c_str());
      else
	throw false;

      // z field
      start = end+1;
      end = entrystr.size();
      //clog << entrystr.substr(start, end-start) << endl;
      if(start < end)
	e.z = atof(entrystr.substr(start, end-start).c_str());
      else
	throw false;

      db->push_front(e);

    }
  return db;
};

int main( int argc, char* argv[] )
{
  // parse args
  vul_arg<char const*> imgdir(0, "DICOM image dir");
  vul_arg<char const*> seginfile(0, "Segmented image", "SupineSegmented.vtk/SupineSegmented.img");
  vul_arg<char const*> outfilename(0, "Output feature filename(no extension)", "PolypCandidatesExtracted");
  vul_arg_parse(argc, argv);

  /* get paths to input/output files */
  string rawinfilename = "";
  rawinfilename.append(imgdir());
  string seginfilename = "";
  seginfilename.append(imgdir());
  seginfilename.append(seginfile());
  string outputVTKname = "";
  outputVTKname.append(outfilename());

  // read in the DICOM series
  ctc::CTCImageReader::Pointer reader = ctc::CTCImageReader::New();
  reader->SetDirectory(rawinfilename);

  // read segmented data
  typedef itk::ImageFileReader< ctc::BinaryImageType > SegDataReaderType;
  SegDataReaderType::Pointer segreader = SegDataReaderType::New();
  segreader->SetFileName(seginfilename);

  try
    {
      reader->Update();
      segreader->Update();
    }
  catch (itk::ExceptionObject &ex)
    {
      std::cout << ex << std::endl;
      return EXIT_FAILURE;
    }

  // extract the features
  typedef ctc::PrincipleCurvatureExtraction FilterType;
  FilterType::Pointer filter = FilterType::New();
  filter->SetBinaryInput(segreader->GetOutput());
  filter->SetImageInput(reader->GetOutput());
  std::clog << "Computing Features ...";
  try
    {
      filter->Compute();
    }
  catch (itk::ExceptionObject &ex)
    {
      std::cout << ex << std::endl;
      return EXIT_FAILURE;
    }
  std::clog << " Done." << std::endl;

    typedef ctc::FeatureExtraction FeatureExtractionFilterType;
    FeatureExtractionFilterType::Pointer FEfilter = FeatureExtractionFilterType::New();
    //FEfilter->SetSeedRegion(filter->GetSeedRegion());
    //FEfilter->SetInitialFeatureVector(filter->GetOutput());

    FEfilter->SetSegmentedImageInput(segreader->GetOutput());
    FEfilter->SetRawImageInput(reader->GetOutput());
    FEfilter->SetOutputVTK(outputVTKname);

    /* Core of feature extraction */
    FEfilter->Analyze();

    return EXIT_SUCCESS;

}
<|endoftext|>


<commit_before>#ifndef RBX_ON_STACK_HPP
#define RBX_ON_STACK_HPP

#include "gc/variable_buffer.hpp"

namespace rubinius {

  class Object;

  template <int size>
  class OnStack {
    VariableRootBuffer buffer_;
    Object** objects_[size];

  public:

    template <typename T>
    OnStack(STATE, T& o1)
      : buffer_(state->vm()->current_root_buffers(), objects_, size)
    {
      // Ok, let me explain.
      // We want to get the address of o1 to put into the buffer, so that
      // the GC can properly update it. We only want this to be used on
      // Objects.
      //
      // Well, we can't declare o1 as Object*& because g++ won't let use use
      // subclasses (ie, Channel*). So we use a template to bring in the data
      // as ANY type.
      //
      // Well, we don't really want any type, we only want Objects! So
      // what we do is validate the type of o1, as expanded by the template,
      // is an Object* or subclass.
      //
      // Thats what the static_cast<> here does. It will only compiled if the
      // type of o1 is Object* or a subclass.
      //
      // When compiled though, because it's completely unused, it disappears, thus
      // we've added a compile time type check.
      //
      (void)static_cast<Object*>(o1);

      // We can't use a static_cast<> here to validate the type of o1 because
      // C++ won't let use do a static cast from, say a Channel** to an Object**.
      // Why? I don't know, probably something to with too much type degradation.
      // Anyway, we work around this using the above type check. If that works out,
      // we're free to use reinterpret_cast<> safely.
      objects_[0] = reinterpret_cast<Object**>(&o1);
    }

    // All the above notes apply to the following overloads as well.

    template <typename T1, typename T2>
    OnStack(STATE, T1& o1, T2& o2)
      : buffer_(state->vm()->current_root_buffers(), objects_, size)
    {
      (void)static_cast<Object*>(o1);
      (void)static_cast<Object*>(o2);

      objects_[0] = reinterpret_cast<Object**>(&o1);
      objects_[1] = reinterpret_cast<Object**>(&o2);
    }

    template <typename T1, typename T2, typename T3>
    OnStack(STATE, T1& o1, T2& o2, T3& o3)
      : buffer_(state->vm()->current_root_buffers(), objects_, size)
    {
      (void)static_cast<Object*>(o1);
      (void)static_cast<Object*>(o2);
      (void)static_cast<Object*>(o3);

      objects_[0] = reinterpret_cast<Object**>(&o1);
      objects_[1] = reinterpret_cast<Object**>(&o2);
      objects_[2] = reinterpret_cast<Object**>(&o3);
    }

    template <typename T1, typename T2, typename T3, typename T4>
    OnStack(STATE, T1& o1, T2& o2, T3& o3, T4& o4)
      : buffer_(state->vm()->current_root_buffers(), objects_, size)
    {
      (void)static_cast<Object*>(o1);
      (void)static_cast<Object*>(o2);
      (void)static_cast<Object*>(o3);
      (void)static_cast<Object*>(o4);

      objects_[0] = reinterpret_cast<Object**>(&o1);
      objects_[1] = reinterpret_cast<Object**>(&o2);
      objects_[2] = reinterpret_cast<Object**>(&o3);
      objects_[3] = reinterpret_cast<Object**>(&o4);
    }

    template <typename T1, typename T2, typename T3, typename T4, typename T5>
    OnStack(STATE, T1& o1, T2& o2, T3& o3, T4& o4, T5& o5)
      : buffer_(state->vm()->current_root_buffers(), objects_, size)
    {
      (void)static_cast<Object*>(o1);
      (void)static_cast<Object*>(o2);
      (void)static_cast<Object*>(o3);
      (void)static_cast<Object*>(o4);
      (void)static_cast<Object*>(o5);

      objects_[0] = reinterpret_cast<Object**>(&o1);
      objects_[1] = reinterpret_cast<Object**>(&o2);
      objects_[2] = reinterpret_cast<Object**>(&o3);
      objects_[3] = reinterpret_cast<Object**>(&o4);
      objects_[4] = reinterpret_cast<Object**>(&o4);
    }

  };
}

#endif
<commit_msg>Fix correction to documentation for OnStack class.<commit_after>#ifndef RBX_ON_STACK_HPP
#define RBX_ON_STACK_HPP

#include "gc/variable_buffer.hpp"

namespace rubinius {

  class Object;

  template <int size>
  class OnStack {
    VariableRootBuffer buffer_;
    Object** objects_[size];

  public:

    template <typename T>
    OnStack(STATE, T& o1)
      : buffer_(state->vm()->current_root_buffers(), objects_, size)
    {
      // Ok, let me explain.
      // We want to get the address of o1 to put into the buffer, so that
      // the GC can properly update it. We only want this to be used on
      // Objects.
      //
      // Well, we can't declare o1 as Object*& because g++ won't let use use
      // subclasses (ie, Channel*). So we use a template to bring in the data
      // as ANY type.
      //
      // Well, we don't really want any type, we only want Objects! So
      // what we do is validate the type of o1, as expanded by the template,
      // is an Object* or subclass.
      //
      // That's what the static_cast<> here does. It will be compiled if and
      // only if the type of o1 is Object* or a subclass.
      //
      // When compiled though, because it's completely unused, it disappears, thus
      // we've added a compile time type check.
      //
      (void)static_cast<Object*>(o1);

      // We can't use a static_cast<> here to validate the type of o1 because
      // C++ won't let use do a static cast from, say a Channel** to an Object**.
      // Why? I don't know, probably something to with too much type degradation.
      // Anyway, we work around this using the above type check. If that works out,
      // we're free to use reinterpret_cast<> safely.
      objects_[0] = reinterpret_cast<Object**>(&o1);
    }

    // All the above notes apply to the following overloads as well.

    template <typename T1, typename T2>
    OnStack(STATE, T1& o1, T2& o2)
      : buffer_(state->vm()->current_root_buffers(), objects_, size)
    {
      (void)static_cast<Object*>(o1);
      (void)static_cast<Object*>(o2);

      objects_[0] = reinterpret_cast<Object**>(&o1);
      objects_[1] = reinterpret_cast<Object**>(&o2);
    }

    template <typename T1, typename T2, typename T3>
    OnStack(STATE, T1& o1, T2& o2, T3& o3)
      : buffer_(state->vm()->current_root_buffers(), objects_, size)
    {
      (void)static_cast<Object*>(o1);
      (void)static_cast<Object*>(o2);
      (void)static_cast<Object*>(o3);

      objects_[0] = reinterpret_cast<Object**>(&o1);
      objects_[1] = reinterpret_cast<Object**>(&o2);
      objects_[2] = reinterpret_cast<Object**>(&o3);
    }

    template <typename T1, typename T2, typename T3, typename T4>
    OnStack(STATE, T1& o1, T2& o2, T3& o3, T4& o4)
      : buffer_(state->vm()->current_root_buffers(), objects_, size)
    {
      (void)static_cast<Object*>(o1);
      (void)static_cast<Object*>(o2);
      (void)static_cast<Object*>(o3);
      (void)static_cast<Object*>(o4);

      objects_[0] = reinterpret_cast<Object**>(&o1);
      objects_[1] = reinterpret_cast<Object**>(&o2);
      objects_[2] = reinterpret_cast<Object**>(&o3);
      objects_[3] = reinterpret_cast<Object**>(&o4);
    }

    template <typename T1, typename T2, typename T3, typename T4, typename T5>
    OnStack(STATE, T1& o1, T2& o2, T3& o3, T4& o4, T5& o5)
      : buffer_(state->vm()->current_root_buffers(), objects_, size)
    {
      (void)static_cast<Object*>(o1);
      (void)static_cast<Object*>(o2);
      (void)static_cast<Object*>(o3);
      (void)static_cast<Object*>(o4);
      (void)static_cast<Object*>(o5);

      objects_[0] = reinterpret_cast<Object**>(&o1);
      objects_[1] = reinterpret_cast<Object**>(&o2);
      objects_[2] = reinterpret_cast<Object**>(&o3);
      objects_[3] = reinterpret_cast<Object**>(&o4);
      objects_[4] = reinterpret_cast<Object**>(&o4);
    }

  };
}

#endif
<|endoftext|>


<commit_before>// @(#)root/eve:$Id$
// Author: Matevz Tadel

// Demonstates usage of automatic 2D projections - class TEveProjectionManager.

const char* esd_geom_file_name =
   "http://root.cern.ch/files/alice_ESDgeometry.root";

void projection()
{
   TFile::SetCacheFileDir(".");
   TEveManager::Create();

   // camera
   TEveScene* s = gEve->SpawnNewScene("Projected Event");
   gEve->GetDefaultViewer()->AddScene(s);
   TGLViewer* v = gEve->GetDefaultGLViewer();
   v->SetCurrentCamera(TGLViewer::kCameraOrthoXOY);
   TGLOrthoCamera* cam = (TGLOrthoCamera*) v->CurrentCamera();
   cam->SetZoomMinMax(0.2, 20);

   // projections
   TEveProjectionManager* mng =
      new TEveProjectionManager(TEveProjection::kPT_RPhi);
   s->AddElement(mng);
   TEveProjectionAxes* axes = new TEveProjectionAxes(mng);
   axes->SetTitle("TEveProjections demo");
   s->AddElement(axes);
   gEve->AddToListTree(axes, kTRUE);
   gEve->AddToListTree(mng, kTRUE);

   // Simple geometry
   TFile* geom = TFile::Open(esd_geom_file_name, "CACHEREAD");
   if (!geom)
      return;

   TEveGeoShapeExtract* gse = (TEveGeoShapeExtract*) geom->Get("Gentle");
   TEveGeoShape* gsre = TEveGeoShape::ImportShapeExtract(gse, 0);
   geom->Close();
   delete geom;
   gsre->SetPickableRecursively(kTRUE);
   gEve->AddGlobalElement(gsre);
   gEve->GetGlobalScene()->SetRnrState(kFALSE);
   mng->ImportElements(gsre);

   TEveLine* line = new TEveLine;
   line->SetMainColor(kGreen);
   for (Int_t i=0; i<160; ++i)
      line->SetNextPoint(120*sin(0.2*i), 120*cos(0.2*i), 80-i);
   gEve->AddElement(line);
   mng->ImportElements(line);
   line->SetRnrSelf(kFALSE);

   gEve->Redraw3D(kTRUE);
}
<commit_msg>Fix invalid type conversion (does CINT check anything at all???).<commit_after>// @(#)root/eve:$Id$
// Author: Matevz Tadel

// Demonstates usage of automatic 2D projections - class TEveProjectionManager.

const char* esd_geom_file_name =
   "http://root.cern.ch/files/alice_ESDgeometry.root";

void projection()
{
   TFile::SetCacheFileDir(".");
   TEveManager::Create();

   // camera
   TEveScene* s = gEve->SpawnNewScene("Projected Event");
   gEve->GetDefaultViewer()->AddScene(s);
   TGLViewer* v = gEve->GetDefaultGLViewer();
   v->SetCurrentCamera(TGLViewer::kCameraOrthoXOY);
   TGLOrthoCamera& cam = (TGLOrthoCamera&) v->CurrentCamera();
   cam.SetZoomMinMax(0.2, 20);

   // projections
   TEveProjectionManager* mng =
      new TEveProjectionManager(TEveProjection::kPT_RPhi);
   s->AddElement(mng);
   TEveProjectionAxes* axes = new TEveProjectionAxes(mng);
   axes->SetTitle("TEveProjections demo");
   s->AddElement(axes);
   gEve->AddToListTree(axes, kTRUE);
   gEve->AddToListTree(mng, kTRUE);

   // Simple geometry
   TFile* geom = TFile::Open(esd_geom_file_name, "CACHEREAD");
   if (!geom)
      return;

   TEveGeoShapeExtract* gse = (TEveGeoShapeExtract*) geom->Get("Gentle");
   TEveGeoShape* gsre = TEveGeoShape::ImportShapeExtract(gse, 0);
   geom->Close();
   delete geom;
   gsre->SetPickableRecursively(kTRUE);
   gEve->AddGlobalElement(gsre);
   gEve->GetGlobalScene()->SetRnrState(kFALSE);
   mng->ImportElements(gsre);

   TEveLine* line = new TEveLine;
   line->SetMainColor(kGreen);
   for (Int_t i=0; i<160; ++i)
      line->SetNextPoint(120*sin(0.2*i), 120*cos(0.2*i), 80-i);
   gEve->AddElement(line);
   mng->ImportElements(line);
   line->SetRnrSelf(kFALSE);

   gEve->Redraw3D(kTRUE);
}
<|endoftext|>


<commit_before>

#include "../common.h"

namespace VM {
    using namespace Lua;

    char HeapManager::heap[HEAP_SIZE];
    char* HeapManager::next_free_block = heap;

    set<char*> HeapManager::gray;

    void HeapManager::read_block_size(char* ptr, unsigned char& block_size) {
        block_size = (unsigned char)*ptr;
    }
    void HeapManager::read_block_flags(char* ptr, char& type, char& color, bool& free) {
        char flags = *(ptr+1);
        type =  (flags & (char)0b11111000) >> 3;
        color = (flags & (char)0b00000110) >> 1;
        free = !(flags & (char)0b00000001);
    }

    void HeapManager::write_block_size(char* ptr, unsigned char block_size) {
        *ptr = block_size;
    }
    void HeapManager::write_block_flags(char* ptr, char type, char color, bool free) {
        char flags = 0;
        flags |= ((type  << 3) & 0b11111000);
        flags |= ((color << 1) & 0b00000110);
        flags |= (!free        & 0b00000001);
        *(ptr+1) = flags;
    }

    char* HeapManager::getAddress(unsigned char alloc_size, unsigned char& block_size) {
        char type,color;
        bool free;

        int p = (int)(next_free_block - heap);
        while (p < HEAP_SIZE - HEAP_HEAD_SIZE - alloc_size) {
            read_block_size(heap+p, block_size);
            read_block_flags(heap+p, type, color, free);

            if (free && (block_size == 0 || alloc_size <= block_size)) { return heap+p; }
            p += FULL_BLOCK_SIZE(block_size);
        }
        return NULL;
    }

    void* HeapManager::allocBlock(unsigned char alloc_size, char type, bool protect) {
        assert(alloc_size <= 255);
        unsigned char block_size;
        char* ptr = getAddress(alloc_size, block_size);

        if (ptr == NULL) {
            printf("We ran out of memory\n");
            exit(1);
        }

#if DEBUG_HEAP_ALLOC
        printf("ALLOC %i %i\n", (int)(ptr - heap), type);
#endif

        int next_free_block_size = 0;

        // I'm not at the end of heap, there is block after me
        if (block_size != 0) {
            next_free_block_size = block_size - alloc_size - HEAP_HEAD_SIZE;

            // if new free block would be smaller than minimum,
            // use whole block as is and do nothing, since we
            // reached other set-up block
            if (next_free_block_size < HEAP_MIN_BLOCK_SIZE) {
                alloc_size = block_size;
            // else create new block with new size
            } else {
                write_block_size(ptr + FULL_BLOCK_SIZE(alloc_size), (unsigned char)next_free_block_size);
                write_block_flags(ptr + FULL_BLOCK_SIZE(alloc_size), 0, 0, 1);
            }
        }

        write_block_size(ptr, alloc_size);
        write_block_flags(ptr, type, (char)(protect ? GC_PROTECTED : GC_WHITE), false);

        if (next_free_block == ptr) {
            next_free_block += FULL_BLOCK_SIZE(alloc_size);
        }

        return ptr + HEAP_HEAD_SIZE;
    }

    void HeapManager::purgeHeap() {

        unsigned char block_size;
        char type, color;
        bool free;

        next_free_block = NULL;
        char* prev_block = NULL;
        unsigned char prev_size = 0;

        int p = 0;
        while (p < HEAP_SIZE - HEAP_HEAD_SIZE - HEAP_MIN_BLOCK_SIZE) {
            char* block = heap+p;

            read_block_size(block, block_size);

            if (block_size == 0) { // reached the end of used space
                if (next_free_block == NULL) { next_free_block = block; }
                if (prev_block != NULL) { write_block_size(prev_block, 0); }
                break;
            }

            read_block_flags(block, type, color, free);

            // free white blocks
            if (!free && color == GC_WHITE) {
                //printf("before: %i\n", free);
                if (type == GC_STRING) {((StringObject*)(block+2))->print();}

#if DEBUG_HEAP_ALLOC
                printf("DEALLOC %i\n", (int)(block - heap));
#endif

                switch(type) {
                    case GC_TABLE:   ((Table*)       (block + HEAP_HEAD_SIZE))->~Table();        break;
                    case GC_UPVAL:   ((UpvalueRef*)  (block + HEAP_HEAD_SIZE))->~UpvalueRef();   break;
                    case GC_CLOSURE: ((Closure*)     (block + HEAP_HEAD_SIZE))->~Closure();      break;
                    case GC_STRING:  ((StringObject*)(block + HEAP_HEAD_SIZE))->~StringObject(); break;
                    case GC_NATIVE:  ((Native*)      (block + HEAP_HEAD_SIZE))->~Native();       break;
                    case GC_FILE:    ((File*)        (block + HEAP_HEAD_SIZE))->~File();         break;
                    default: break;
                }
                free = true;
            }

            if (!free) {
                write_block_flags(block, type, (char)(color == GC_PROTECTED ? GC_PROTECTED : GC_WHITE), free);
                prev_block = NULL;
            } else {
                if (next_free_block == NULL) { next_free_block = block; }

                // if possible, merge with previous free block
                if (prev_block != NULL && prev_size + block_size + HEAP_HEAD_SIZE <= HEAP_MAX_BLOCK_SIZE) {
                    write_block_size(prev_block, (unsigned char)(prev_size + block_size + HEAP_HEAD_SIZE));
                // otherwise just mark block as free
                } else {
                    write_block_flags(block, type, GC_WHITE, free);
                    prev_block = block;
                    prev_size = block_size;
                }
            }

            p += FULL_BLOCK_SIZE(block_size);
        }
    }

    void HeapManager::markGray(char* ptr) {
        if (gray.find(ptr) == gray.end()) {
            char dummy_type;
            char color;
            bool free;

            char* block_ptr = ptr - HEAP_HEAD_SIZE;

            // if not gray check if white
            read_block_flags(block_ptr, dummy_type, color, free);

            //printf("INDEX = %i\n", (ptr - HeapManager::heap - 2));
            //printf("TYPE = %i\n", dummy_type);

            assert(!free); // sanity check
            if (color == GC_WHITE) {
                write_block_flags(block_ptr, dummy_type, GC_GRAY, free);
                gray.insert(ptr);
            }
        }
    }

    void HeapManager::markReferencesGray() {
        char type, dummy_color;
        bool dummy_free;

        for (std::set<char*>::iterator ptr = gray.begin(); ptr != gray.end();) {
            char* block_ptr = (*ptr) - HEAP_HEAD_SIZE;
            read_block_flags(block_ptr, type, dummy_color, dummy_free);

            ((GCObject*)*ptr)->gc(); // mark all references from the object gray
            write_block_flags(block_ptr, type, GC_BLACK, dummy_free);

            ptr = gray.erase(ptr);
        }
    }

    void HeapManager::print() {

        unsigned char block_size;
        char type;
        char color;
        bool free;
        int p = 0;

        printf("Skipping protected\n");
        while(p < HEAP_SIZE - HEAP_HEAD_SIZE) {
            read_block_size(heap+p, block_size);
            read_block_flags(heap+p, type, color, free);

            if (color != GC_PROTECTED) {
                if (block_size == 0) { // reached free space at the and of the heap
                    double left = (HEAP_SIZE - p)/1024.;
                    printf("%.3f kB (%.3f MB) left\n\n", left, left/1024.);
                    break;
                }

                switch(color) {
                    case GC_WHITE: printf("W"); break;
                    case GC_BLACK: printf("B"); break;
                    case GC_GRAY:  printf("G"); break;
                    case GC_PROTECTED:  printf("*"); break;
                    default: break;
                }

                printf(" Block [%i] @%i: %iB", free, p, block_size);
                if (!free) {
                    switch(type) {
                        case GC_TABLE:   printf(", table"); break;
                        case GC_UPVAL:   printf(", upval"); break;
                        case GC_CLOSURE: printf(", closure"); break;
                        case GC_STRING:  printf(", string"); break;
                        case GC_NATIVE:  printf(", native"); break;
                        case GC_FILE:    printf(", file"); break;
                        default: printf("unknown"); break;
                    }
                }
                printf("\n");
            }

            p += HEAP_HEAD_SIZE + block_size;
        }
    }

    void HeapManager::printStatus() {

        int free_blocks = 0, used_blocks = 0;
        int free_memory = 0, used_memory = 0;

        unsigned char block_size;
        char type, color;
        bool free;
        int p = 0;
        while(p < HEAP_SIZE - HEAP_HEAD_SIZE) {
            read_block_size(heap+p, block_size);
            read_block_flags(heap+p, type, color, free);

            if (block_size == 0) { // reached free space at the and of the heap
                printf("Free: %.3f kB (%i blocks), used: %.3f kB (%i blocks)\n",
                       free_memory/1024., free_blocks,
                       used_memory/1024., used_blocks);
                double left = (HEAP_SIZE - p)/1024.;
                printf("%.3f kB (%.3f MB) left\n\n", left, left/1024.);
                break;
            }

            if (free) {
                free_blocks++;
                free_memory += block_size;
            } else {
                used_blocks++;
                used_memory += block_size;
            }

            p += HEAP_HEAD_SIZE + block_size;
        }
    }

}
<commit_msg>Remove debug print<commit_after>

#include "../common.h"

namespace VM {
    using namespace Lua;

    char HeapManager::heap[HEAP_SIZE];
    char* HeapManager::next_free_block = heap;

    set<char*> HeapManager::gray;

    void HeapManager::read_block_size(char* ptr, unsigned char& block_size) {
        block_size = (unsigned char)*ptr;
    }
    void HeapManager::read_block_flags(char* ptr, char& type, char& color, bool& free) {
        char flags = *(ptr+1);
        type =  (flags & (char)0b11111000) >> 3;
        color = (flags & (char)0b00000110) >> 1;
        free = !(flags & (char)0b00000001);
    }

    void HeapManager::write_block_size(char* ptr, unsigned char block_size) {
        *ptr = block_size;
    }
    void HeapManager::write_block_flags(char* ptr, char type, char color, bool free) {
        char flags = 0;
        flags |= ((type  << 3) & 0b11111000);
        flags |= ((color << 1) & 0b00000110);
        flags |= (!free        & 0b00000001);
        *(ptr+1) = flags;
    }

    char* HeapManager::getAddress(unsigned char alloc_size, unsigned char& block_size) {
        char type,color;
        bool free;

        int p = (int)(next_free_block - heap);
        while (p < HEAP_SIZE - HEAP_HEAD_SIZE - alloc_size) {
            read_block_size(heap+p, block_size);
            read_block_flags(heap+p, type, color, free);

            if (free && (block_size == 0 || alloc_size <= block_size)) { return heap+p; }
            p += FULL_BLOCK_SIZE(block_size);
        }
        return NULL;
    }

    void* HeapManager::allocBlock(unsigned char alloc_size, char type, bool protect) {
        assert(alloc_size <= 255);
        unsigned char block_size;
        char* ptr = getAddress(alloc_size, block_size);

        if (ptr == NULL) {
            printf("We ran out of memory\n");
            exit(1);
        }

#if DEBUG_HEAP_ALLOC
        printf("ALLOC %i %i\n", (int)(ptr - heap), type);
#endif

        int next_free_block_size = 0;

        // I'm not at the end of heap, there is block after me
        if (block_size != 0) {
            next_free_block_size = block_size - alloc_size - HEAP_HEAD_SIZE;

            // if new free block would be smaller than minimum,
            // use whole block as is and do nothing, since we
            // reached other set-up block
            if (next_free_block_size < HEAP_MIN_BLOCK_SIZE) {
                alloc_size = block_size;
            // else create new block with new size
            } else {
                write_block_size(ptr + FULL_BLOCK_SIZE(alloc_size), (unsigned char)next_free_block_size);
                write_block_flags(ptr + FULL_BLOCK_SIZE(alloc_size), 0, 0, 1);
            }
        }

        write_block_size(ptr, alloc_size);
        write_block_flags(ptr, type, (char)(protect ? GC_PROTECTED : GC_WHITE), false);

        if (next_free_block == ptr) {
            next_free_block += FULL_BLOCK_SIZE(alloc_size);
        }

        return ptr + HEAP_HEAD_SIZE;
    }

    void HeapManager::purgeHeap() {

        unsigned char block_size;
        char type, color;
        bool free;

        next_free_block = NULL;
        char* prev_block = NULL;
        unsigned char prev_size = 0;

        int p = 0;
        while (p < HEAP_SIZE - HEAP_HEAD_SIZE - HEAP_MIN_BLOCK_SIZE) {
            char* block = heap+p;

            read_block_size(block, block_size);

            if (block_size == 0) { // reached the end of used space
                if (next_free_block == NULL) { next_free_block = block; }
                if (prev_block != NULL) { write_block_size(prev_block, 0); }
                break;
            }

            read_block_flags(block, type, color, free);

            // free white blocks
            if (!free && color == GC_WHITE) {

#if DEBUG_HEAP_ALLOC
                printf("DEALLOC %i\n", (int)(block - heap));
#endif

                switch(type) {
                    case GC_TABLE:   ((Table*)       (block + HEAP_HEAD_SIZE))->~Table();        break;
                    case GC_UPVAL:   ((UpvalueRef*)  (block + HEAP_HEAD_SIZE))->~UpvalueRef();   break;
                    case GC_CLOSURE: ((Closure*)     (block + HEAP_HEAD_SIZE))->~Closure();      break;
                    case GC_STRING:  ((StringObject*)(block + HEAP_HEAD_SIZE))->~StringObject(); break;
                    case GC_NATIVE:  ((Native*)      (block + HEAP_HEAD_SIZE))->~Native();       break;
                    case GC_FILE:    ((File*)        (block + HEAP_HEAD_SIZE))->~File();         break;
                    default: break;
                }
                free = true;
            }

            if (!free) {
                write_block_flags(block, type, (char)(color == GC_PROTECTED ? GC_PROTECTED : GC_WHITE), free);
                prev_block = NULL;
            } else {
                if (next_free_block == NULL) { next_free_block = block; }

                // if possible, merge with previous free block
                if (prev_block != NULL && prev_size + block_size + HEAP_HEAD_SIZE <= HEAP_MAX_BLOCK_SIZE) {
                    write_block_size(prev_block, (unsigned char)(prev_size + block_size + HEAP_HEAD_SIZE));
                // otherwise just mark block as free
                } else {
                    write_block_flags(block, type, GC_WHITE, free);
                    prev_block = block;
                    prev_size = block_size;
                }
            }

            p += FULL_BLOCK_SIZE(block_size);
        }
    }

    void HeapManager::markGray(char* ptr) {
        if (gray.find(ptr) == gray.end()) {
            char dummy_type;
            char color;
            bool free;

            char* block_ptr = ptr - HEAP_HEAD_SIZE;

            // if not gray check if white
            read_block_flags(block_ptr, dummy_type, color, free);

            //printf("INDEX = %i\n", (ptr - HeapManager::heap - 2));
            //printf("TYPE = %i\n", dummy_type);

            assert(!free); // sanity check
            if (color == GC_WHITE) {
                write_block_flags(block_ptr, dummy_type, GC_GRAY, free);
                gray.insert(ptr);
            }
        }
    }

    void HeapManager::markReferencesGray() {
        char type, dummy_color;
        bool dummy_free;

        for (std::set<char*>::iterator ptr = gray.begin(); ptr != gray.end();) {
            char* block_ptr = (*ptr) - HEAP_HEAD_SIZE;
            read_block_flags(block_ptr, type, dummy_color, dummy_free);

            ((GCObject*)*ptr)->gc(); // mark all references from the object gray
            write_block_flags(block_ptr, type, GC_BLACK, dummy_free);

            ptr = gray.erase(ptr);
        }
    }

    void HeapManager::print() {

        unsigned char block_size;
        char type;
        char color;
        bool free;
        int p = 0;

        printf("Skipping protected\n");
        while(p < HEAP_SIZE - HEAP_HEAD_SIZE) {
            read_block_size(heap+p, block_size);
            read_block_flags(heap+p, type, color, free);

            if (color != GC_PROTECTED) {
                if (block_size == 0) { // reached free space at the and of the heap
                    double left = (HEAP_SIZE - p)/1024.;
                    printf("%.3f kB (%.3f MB) left\n\n", left, left/1024.);
                    break;
                }

                switch(color) {
                    case GC_WHITE: printf("W"); break;
                    case GC_BLACK: printf("B"); break;
                    case GC_GRAY:  printf("G"); break;
                    case GC_PROTECTED:  printf("*"); break;
                    default: break;
                }

                printf(" Block [%i] @%i: %iB", free, p, block_size);
                if (!free) {
                    switch(type) {
                        case GC_TABLE:   printf(", table"); break;
                        case GC_UPVAL:   printf(", upval"); break;
                        case GC_CLOSURE: printf(", closure"); break;
                        case GC_STRING:  printf(", string"); break;
                        case GC_NATIVE:  printf(", native"); break;
                        case GC_FILE:    printf(", file"); break;
                        default: printf("unknown"); break;
                    }
                }
                printf("\n");
            }

            p += HEAP_HEAD_SIZE + block_size;
        }
    }

    void HeapManager::printStatus() {

        int free_blocks = 0, used_blocks = 0;
        int free_memory = 0, used_memory = 0;

        unsigned char block_size;
        char type, color;
        bool free;
        int p = 0;
        while(p < HEAP_SIZE - HEAP_HEAD_SIZE) {
            read_block_size(heap+p, block_size);
            read_block_flags(heap+p, type, color, free);

            if (block_size == 0) { // reached free space at the and of the heap
                printf("Free: %.3f kB (%i blocks), used: %.3f kB (%i blocks)\n",
                       free_memory/1024., free_blocks,
                       used_memory/1024., used_blocks);
                double left = (HEAP_SIZE - p)/1024.;
                printf("%.3f kB (%.3f MB) left\n\n", left, left/1024.);
                break;
            }

            if (free) {
                free_blocks++;
                free_memory += block_size;
            } else {
                used_blocks++;
                used_memory += block_size;
            }

            p += HEAP_HEAD_SIZE + block_size;
        }
    }

}
<|endoftext|>


<commit_before>#include "float.h"
#include "gd.h"
#include "vw.h"

namespace MULTILABEL
{
bool is_test_label(labels& ld)
{ if (ld.label_v.size() == 0)
    return true;
  else
    return false;
}

char* bufread_label(labels* ld, char* c, io_buf& cache)
{ size_t num = *(size_t *)c;
  ld->label_v.erase();
  c += sizeof(size_t);
  size_t total = sizeof(uint32_t)*num;
  if (buf_read(cache, c, (int)total) < total)
  { cout << "error in demarshal of cost data" << endl;
    return c;
  }
  for (size_t i = 0; i<num; i++)
  { uint32_t temp = *(uint32_t *)c;
    c += sizeof(uint32_t);
    ld->label_v.push_back(temp);
  }

  return c;
}

size_t read_cached_label(shared_data*, void* v, io_buf& cache)
{ labels* ld = (labels*) v;
  ld->label_v.erase();
  char *c;
  size_t total = sizeof(size_t);
  if (buf_read(cache, c, (int)total) < total)
    return 0;
  bufread_label(ld,c, cache);

  return total;
}

float weight(void*)
{ return 1.;
}

char* bufcache_label(labels* ld, char* c)
{ *(size_t *)c = ld->label_v.size();
  c += sizeof(size_t);
  for (unsigned int i = 0; i< ld->label_v.size(); i++)
  { *(uint32_t *)c = ld->label_v[i];
    c += sizeof(uint32_t);
  }
  return c;
}

void cache_label(void* v, io_buf& cache)
{ char *c;
  labels* ld = (labels*) v;
  buf_write(cache, c, sizeof(size_t)+sizeof(uint32_t)*ld->label_v.size());
  bufcache_label(ld,c);
}

void default_label(void* v)
{ labels* ld = (labels*) v;
  ld->label_v.erase();
}

void delete_label(void* v)
{ labels* ld = (labels*)v;
  if (ld) ld->label_v.delete_v();
}

void copy_label(void* dst, void* src)
{ if (dst && src)
  { labels* ldD = (labels*)dst;
    labels* ldS = (labels*)src;
    copy_array(ldD->label_v, ldS->label_v);
  }
}

void parse_label(parser* p, shared_data*, void* v, v_array<substring>& words)
{ labels* ld = (labels*)v;

  ld->label_v.erase();
  switch(words.size())
  { case 0:
      break;
    case 1:
      tokenize(',', words[0], p->parse_name);

      for (size_t i = 0; i < p->parse_name.size(); i++)
      { *(p->parse_name[i].end) = '\0';
        uint32_t n = atoi(p->parse_name[i].begin);
        ld->label_v.push_back(n);
      }
      break;
    default:
      cerr << "example with an odd label, what is ";
      for (size_t i = 0; i < words.size(); i++)
        cerr << words[i].begin << " ";
      cerr << endl;
  }
}

label_parser multilabel = {default_label, parse_label,
                           cache_label, read_cached_label,
                           delete_label, weight,
                           copy_label,
                           sizeof(labels)
                          };

void print_update(vw& all, bool is_test, example& ec)
{ if (all.sd->weighted_examples >= all.sd->dump_interval && !all.quiet && !all.bfgs)
  { stringstream label_string;
    if (is_test)
      label_string << " unknown";
    else
      for(size_t i = 0; i < ec.l.multilabels.label_v.size(); i++)
        label_string << " " << ec.l.multilabels.label_v[i];

    stringstream pred_string;
    for(size_t i = 0; i < ec.pred.multilabels.label_v.size(); i++)
      pred_string << " " << ec.pred.multilabels.label_v[i];

    all.sd->print_update(all.holdout_set_off, all.current_pass, label_string.str(), pred_string.str(),
                         ec.num_features, all.progress_add, all.progress_arg);
  }
}

void print_multilabel(int f, labels& mls, v_array<char>&)
{ if (f >= 0)
  { std::stringstream ss;

    for (size_t i = 0; i < mls.label_v.size(); i++)
    { if (i > 0)
        ss << ',';
      ss << mls.label_v[i];
    }
    ss << '\n';
    ssize_t len = ss.str().size();
    ssize_t t = io_buf::write_file_or_socket(f, ss.str().c_str(), (unsigned int)len);
    if (t != len)
      cerr << "write error: " << strerror(errno) << endl;
  }
}

void output_example(vw& all, example& ec)
{ labels& ld = ec.l.multilabels;

  float loss = 0.;
  if (!is_test_label(ld))
  { //need to compute exact loss
    labels preds = ec.pred.multilabels;
    labels given = ec.l.multilabels;

    uint32_t preds_index = 0;
    uint32_t given_index = 0;

    while(preds_index < preds.label_v.size() && given_index < given.label_v.size())
    { if (preds.label_v[preds_index] < given.label_v[given_index])
        preds_index++;
      else if (preds.label_v[preds_index] > given.label_v[given_index])
      { given_index++;
        loss++;
      }
      else
      { preds_index++;
        given_index++;
      }
    }
    loss += given.label_v.size() - given_index;
  }

  all.sd->update(ec.test_only, loss, 1.f, ec.num_features);

  for (int* sink = all.final_prediction_sink.begin; sink != all.final_prediction_sink.end; sink++)
    print_multilabel(*sink, ec.pred.multilabels, ec.tag);

  print_update(all, is_test_label(ec.l.multilabels), ec);
}

bool example_is_test(example& ec)
{ return is_test_label(ec.l.multilabels);
}
}
<commit_msg>multilabel hamming loss bugfix<commit_after>#include "float.h"
#include "gd.h"
#include "vw.h"

namespace MULTILABEL
{
bool is_test_label(labels& ld)
{ if (ld.label_v.size() == 0)
    return true;
  else
    return false;
}

char* bufread_label(labels* ld, char* c, io_buf& cache)
{ size_t num = *(size_t *)c;
  ld->label_v.erase();
  c += sizeof(size_t);
  size_t total = sizeof(uint32_t)*num;
  if (buf_read(cache, c, (int)total) < total)
  { cout << "error in demarshal of cost data" << endl;
    return c;
  }
  for (size_t i = 0; i<num; i++)
  { uint32_t temp = *(uint32_t *)c;
    c += sizeof(uint32_t);
    ld->label_v.push_back(temp);
  }

  return c;
}

size_t read_cached_label(shared_data*, void* v, io_buf& cache)
{ labels* ld = (labels*) v;
  ld->label_v.erase();
  char *c;
  size_t total = sizeof(size_t);
  if (buf_read(cache, c, (int)total) < total)
    return 0;
  bufread_label(ld,c, cache);

  return total;
}

float weight(void*)
{ return 1.;
}

char* bufcache_label(labels* ld, char* c)
{ *(size_t *)c = ld->label_v.size();
  c += sizeof(size_t);
  for (unsigned int i = 0; i< ld->label_v.size(); i++)
  { *(uint32_t *)c = ld->label_v[i];
    c += sizeof(uint32_t);
  }
  return c;
}

void cache_label(void* v, io_buf& cache)
{ char *c;
  labels* ld = (labels*) v;
  buf_write(cache, c, sizeof(size_t)+sizeof(uint32_t)*ld->label_v.size());
  bufcache_label(ld,c);
}

void default_label(void* v)
{ labels* ld = (labels*) v;
  ld->label_v.erase();
}

void delete_label(void* v)
{ labels* ld = (labels*)v;
  if (ld) ld->label_v.delete_v();
}

void copy_label(void* dst, void* src)
{ if (dst && src)
  { labels* ldD = (labels*)dst;
    labels* ldS = (labels*)src;
    copy_array(ldD->label_v, ldS->label_v);
  }
}

void parse_label(parser* p, shared_data*, void* v, v_array<substring>& words)
{ labels* ld = (labels*)v;

  ld->label_v.erase();
  switch(words.size())
  { case 0:
      break;
    case 1:
      tokenize(',', words[0], p->parse_name);

      for (size_t i = 0; i < p->parse_name.size(); i++)
      { *(p->parse_name[i].end) = '\0';
        uint32_t n = atoi(p->parse_name[i].begin);
        ld->label_v.push_back(n);
      }
      break;
    default:
      cerr << "example with an odd label, what is ";
      for (size_t i = 0; i < words.size(); i++)
        cerr << words[i].begin << " ";
      cerr << endl;
  }
}

label_parser multilabel = {default_label, parse_label,
                           cache_label, read_cached_label,
                           delete_label, weight,
                           copy_label,
                           sizeof(labels)
                          };

void print_update(vw& all, bool is_test, example& ec)
{ if (all.sd->weighted_examples >= all.sd->dump_interval && !all.quiet && !all.bfgs)
  { stringstream label_string;
    if (is_test)
      label_string << " unknown";
    else
      for(size_t i = 0; i < ec.l.multilabels.label_v.size(); i++)
        label_string << " " << ec.l.multilabels.label_v[i];

    stringstream pred_string;
    for(size_t i = 0; i < ec.pred.multilabels.label_v.size(); i++)
      pred_string << " " << ec.pred.multilabels.label_v[i];

    all.sd->print_update(all.holdout_set_off, all.current_pass, label_string.str(), pred_string.str(),
                         ec.num_features, all.progress_add, all.progress_arg);
  }
}

void print_multilabel(int f, labels& mls, v_array<char>&)
{ if (f >= 0)
  { std::stringstream ss;

    for (size_t i = 0; i < mls.label_v.size(); i++)
    { if (i > 0)
        ss << ',';
      ss << mls.label_v[i];
    }
    ss << '\n';
    ssize_t len = ss.str().size();
    ssize_t t = io_buf::write_file_or_socket(f, ss.str().c_str(), (unsigned int)len);
    if (t != len)
      cerr << "write error: " << strerror(errno) << endl;
  }
}

void output_example(vw& all, example& ec)
{ labels& ld = ec.l.multilabels;

  float loss = 0.;
  if (!is_test_label(ld))
  { //need to compute exact loss
    labels preds = ec.pred.multilabels;
    labels given = ec.l.multilabels;

    uint32_t preds_index = 0;
    uint32_t given_index = 0;

    while(preds_index < preds.label_v.size() && given_index < given.label_v.size())
    { if (preds.label_v[preds_index] < given.label_v[given_index])
        preds_index++;
      else if (preds.label_v[preds_index] > given.label_v[given_index])
      { given_index++;
        loss++;
      }
      else
      { preds_index++;
        given_index++;
      }
    }
    loss += given.label_v.size() - given_index;
    loss += preds.label_v.size() - preds_index;
  }

  all.sd->update(ec.test_only, loss, 1.f, ec.num_features);

  for (int* sink = all.final_prediction_sink.begin; sink != all.final_prediction_sink.end; sink++)
    print_multilabel(*sink, ec.pred.multilabels, ec.tag);

  print_update(all, is_test_label(ec.l.multilabels), ec);
}

bool example_is_test(example& ec)
{ return is_test_label(ec.l.multilabels);
}
}
<|endoftext|>