<commit_before>#include <microscopes/lda/model.hpp>

microscopes::lda::model_definition::model_definition(size_t n, size_t v)
    : n_(n), v_(v)
{
    MICROSCOPES_DCHECK(n > 0, "no docs");
    MICROSCOPES_DCHECK(v > 0, "no terms");
}

microscopes::lda::state::state(const model_definition &defn,
      float alpha,
      float beta,
      float gamma,
      const microscopes::lda::nested_vector &docs)
    : V(defn.v()),
      alpha_(alpha),
      beta_(beta),
      gamma_(gamma),
      x_ji(docs),
      n_k(lda_util::defaultdict<size_t, float>(beta * defn.v()))
      {
        // This page intentionally left blank
}

microscopes::lda::state::state(const model_definition &defn,
      float alpha,
      float beta,
      float gamma,
      size_t initial_dishes,
      const microscopes::lda::nested_vector &docs,
      common::rng_t &rng)
    : state(defn, alpha, beta, gamma, docs) {

    auto dish_pool = microscopes::common::util::range(initial_dishes);

    create_dish(); // Dummy dish
    for (size_t eid = 0; eid < nentities(); ++eid) {
        create_entity(eid);

        auto did = common::util::sample_choice(dish_pool, rng);
        if (did > dishes_.back()){
            did = create_dish();
        }
        create_table(eid, did);
    }
}

microscopes::lda::state::state(const model_definition &defn,
      float alpha,
      float beta,
      float gamma,
      const microscopes::lda::nested_vector &dish_assignments,
      const microscopes::lda::nested_vector &table_assignments,
      const microscopes::lda::nested_vector &docs)
    : state(defn, alpha, beta, gamma, docs) {
        // Explicit initialization constructor for state used for
        // deserialization and testing
        // table_assignment maps words to tables (and should be the same
        //  shape as docs)
        // dish_assignment maps tables to dishes (its outer length should
        //  be the the same as docs. Its inner length one plus the maximum
        //  table index value for the given entity/doc.)

        // Create all the dishes we will need.
        create_dish(); // dummy dish
        auto num_dishes = lda_util::max_element(dish_assignments);
        for(size_t dish = 0; dish <= num_dishes; dish++) {
            create_dish();
        }
        for (size_t eid = 0; eid < nentities(); ++eid) {
            create_entity(eid);
            // Create all the tables we will need and assign them to their dish.
            for(auto did: dish_assignments[eid]){
                create_table(eid, did);
            }
            // Assign words to tables.
            for(size_t word_index = 0; word_index < table_assignments[eid].size(); word_index++){
                auto tid  = table_assignments[eid][word_index];
                add_table(eid, tid, word_index);
            }
        }
}

void
microscopes::lda::state::create_entity(size_t eid){
    using_t.push_back(std::vector<size_t>());
    n_jt.push_back(std::vector<size_t>());
    dish_assignments_.push_back(std::vector<size_t>());
    table_assignments_.push_back(std::vector<size_t>(nterms(eid), 0));
    n_jtv.push_back(std::vector< std::map<size_t, size_t>>());
}

microscopes::lda::nested_vector
microscopes::lda::state::assignments() {
    microscopes::lda::nested_vector ret;
    ret.resize(nentities());

    for (size_t eid = 0; eid < nentities(); eid++) {
        ret[eid].resize(table_assignments_[eid].size());
        for (size_t did = 0; did < table_assignments_[eid].size(); did++) {
            auto table = table_assignments_[eid][did];
            ret[eid][did] = dish_assignments_[eid][table];
        }
    }
    return ret;

}

/**
* Returns, for each entity, a map from
* table IDs -> (global) dish assignments
*
*/
microscopes::lda::nested_vector
microscopes::lda::state::dish_assignments() {
    return dish_assignments_;
}

/**
* Returns, for each entity, an assignment vector
* from each word to the (local) table it is assigned to.
*
*/
microscopes::lda::nested_vector
microscopes::lda::state::table_assignments() {
    return table_assignments_;
}

float
microscopes::lda::state::score_assignment() const
{
    return 0;
}

float
microscopes::lda::state::score_data(common::rng_t &rng) const
{
    return 0;
}

std::vector<std::map<size_t, float>>
microscopes::lda::state::word_distribution() {
    // Distribution over words for each topic
    std::vector<std::map<size_t, float>> vec;
    vec.reserve(dishes_.size());
    for (auto k : dishes_) {
        if (k == 0) continue;
        vec.push_back(std::map<size_t, float>());
        for (size_t v = 0; v < V; ++v) {
            vec.back()[v] = n_kv[k].get(v) / n_k.get(k);
        }
    }
    return vec;
}

std::vector<std::vector<float>>
microscopes::lda::state::document_distribution  () {
    // Distribution over topics for each document
    std::vector<std::vector<float>> theta;
    theta.reserve(dish_assignments_.size());
    std::vector<float> am_k(m_k.begin(), m_k.end());
    am_k[0] = gamma_;
    double sum_am_dishes_ = 0;
    for (auto k : dishes_) {
        sum_am_dishes_ += am_k[k];
    }
    for (size_t i = 0; i < am_k.size(); ++i) {
        am_k[i] *= alpha_ / sum_am_dishes_;
    }

    for (size_t j = 0; j < dish_assignments_.size(); j++) {
        std::vector<size_t> &n_jt_ = n_jt[j];
        std::vector<float> p_jk = am_k;
        for (auto t : using_t[j]) {
            if (t == 0) continue;
            size_t k = dish_assignments_[j][t];
            p_jk[k] += n_jt_[t];
        }
        p_jk = lda_util::selectByIndex(p_jk, dishes_);
        lda_util::normalize<float>(p_jk);
        theta.push_back(p_jk);
    }
    return theta;
}

double
microscopes::lda::state::perplexity() {
    std::vector<std::map<size_t, float>> phi = word_distribution();
    std::vector<std::vector<float>> theta = document_distribution();
    phi.insert(phi.begin(), std::map<size_t, float>());
    double log_likelihood = 0;
    size_t N = 0;
    for (size_t eid = 0; eid < nentities(); eid++) {
        for (auto &v : get_entity(eid)) {
            double word_prob = 0;
            for (size_t did = 0; did < dishes_.size(); did++) {
                MICROSCOPES_DCHECK(theta[eid].size() == dishes_.size(), "theta[eid] wrong");
                // Probability that topic of word occurs in document
                // times probability word occurs in topic
                word_prob += theta[eid][did] * phi[did][v];
            }
            log_likelihood -= distributions::fast_log(word_prob);
        }
        N += nterms(eid);
    }

    return exp(log_likelihood / N);
}

// private:

void
microscopes::lda::state::leave_from_dish(size_t j, size_t t) {
    size_t k = dish_assignments_[j][t];
    MICROSCOPES_DCHECK(k > 0, "k < = 0");
    MICROSCOPES_DCHECK(m_k[k] > 0, "m_k[k] <= 0");
    m_k[k] -= 1; // one less table for topic k
    if (m_k[k] == 0) // destroy table
    {
        delete_dish(k);
        dish_assignments_[j][t] = 0;
    }
}

void
microscopes::lda::state::validate_n_k_values() {
    return;
    std::map<size_t, std::tuple<float, float>> values;
    for (auto k : dishes_) {
        float n_kv_sum = 0;
        for (size_t v = 0; v < V; v++) {
            n_kv_sum += n_kv[k].get(v);
        }
        values[k] = std::tuple<float, float>(n_kv_sum, n_k.get(k));
    }
    for (auto kv : values) {
        if (kv.first == 0) continue;
        MICROSCOPES_CHECK(std::abs((std::get<0>(kv.second) - std::get<1>(kv.second))) < 0.01,
                          "n_kv doesn't match n_k");
    }
}

void
microscopes::lda::state::seat_at_dish(size_t j, size_t t, size_t k_new) {
    m_k[k_new] += 1;

    size_t k_old = dish_assignments_[j][t];
    if (k_new != k_old)
    {
        MICROSCOPES_DCHECK(k_new != 0, "k_new is 0");
        dish_assignments_[j][t] = k_new;
        float n_jt_val = n_jt[j][t];

        if (k_old != 0)
        {
            n_k.decr(k_old, n_jt_val);
        }
        n_k.incr(k_new, n_jt_val);
        for (auto kv : n_jtv[j][t]) {
            auto v = kv.first;
            auto n = kv.second;
            MICROSCOPES_DCHECK(v < nwords(), "Word out of bounds");
            if (k_old != 0)
            {
                n_kv[k_old].decr(v, n);
            }
            n_kv[k_new].incr(v, n);
        }
    }
}

void
microscopes::lda::state::add_table(size_t eid, size_t tid, size_t word_index) {
    table_assignments_[eid][word_index] = tid;
    n_jt[eid][tid] += 1;

    size_t k_new = dish_assignments_[eid][tid];
    n_k.incr(k_new, 1);

    size_t v = get_word(eid, word_index);
    MICROSCOPES_DCHECK(v < nwords(), "Word out of bounds");
    n_kv[k_new].incr(v, 1);
    n_jtv[eid][tid][v] += 1;
}

void
microscopes::lda::state::create_dish(size_t k_new){
    while(k_new >= m_k.size())
    {
        m_k.push_back(0);
        n_kv.push_back(lda_util::defaultdict<size_t, float>(beta_));
    }

    dishes_.insert(dishes_.begin() + k_new, k_new);
    n_k.set(k_new, beta_ * V);
    n_kv[k_new] = lda_util::defaultdict<size_t, float>(beta_);
    m_k[k_new] = 0;
}

size_t
microscopes::lda::state::create_dish() {
    size_t k_new = dishes_.size();
    for (size_t i = 0; i < dishes_.size(); ++i)
    {
        if (i != dishes_[i])
        {
            k_new = i;
            break;
        }
    }
    create_dish(k_new);
    return k_new;

}

size_t
microscopes::lda::state::create_table(size_t eid, size_t k_new)
{
    size_t t_new = using_t[eid].size();
    for (size_t i = 0; i < using_t[eid].size(); ++i)
    {
        if (i != using_t[eid][i])
        {
            t_new = i;
            break;
        }
    }
    if (t_new == using_t[eid].size())
    {
        n_jt[eid].push_back(0);
        dish_assignments_[eid].push_back(0);

        n_jtv[eid].push_back(std::map<size_t, size_t>());
    }
    using_t[eid].insert(using_t[eid].begin() + t_new, t_new);
    n_jt[eid][t_new] = 0;
    dish_assignments_[eid][t_new] = k_new;
    if (k_new != 0){
        m_k[k_new] += 1;
    }
    return t_new;
}

void
microscopes::lda::state::remove_table(size_t eid, size_t word_index) {
    size_t tid = table_assignments_[eid][word_index];
    if (tid > 0)
    {
        size_t k = dish_assignments_[eid][tid];
        MICROSCOPES_DCHECK(k > 0, "k <= 0");
        // decrease counters
        size_t v = get_word(eid, word_index);
        MICROSCOPES_DCHECK(v < nwords(), "Word out of bounds");
        n_kv[k].decr(v, 1);
        n_k.decr(k, 1);
        n_jt[eid][tid] -= 1;
        n_jtv[eid][tid][v] -= 1;

        if (n_jt[eid][tid] == 0)
        {
            delete_table(eid, tid);
        }
    }
}

void
microscopes::lda::state::delete_table(size_t eid, size_t tid) {
    size_t k = dish_assignments_[eid][tid];
    lda_util::removeFirst(using_t[eid], tid);
    m_k[k] -= 1;
    MICROSCOPES_DCHECK(m_k[k] >= 0, "m_k[k] < 0");
    if (m_k[k] == 0)
    {
        delete_dish(k);
    }

    // Prune dish assignment vector
    dish_assignments_[eid][tid] = 0;
    while(dish_assignments_[eid].empty() == false)
   {
        if(dish_assignments_[eid].back() == 0){
            dish_assignments_[eid].pop_back();
            n_jt[eid].pop_back();
            n_jtv[eid].pop_back();
        }
        else break;
   }

}

<commit_msg>Allow for gaps in dish indices on explicit initialization<commit_after>#include <microscopes/lda/model.hpp>

microscopes::lda::model_definition::model_definition(size_t n, size_t v)
    : n_(n), v_(v)
{
    MICROSCOPES_DCHECK(n > 0, "no docs");
    MICROSCOPES_DCHECK(v > 0, "no terms");
}

microscopes::lda::state::state(const model_definition &defn,
      float alpha,
      float beta,
      float gamma,
      const microscopes::lda::nested_vector &docs)
    : V(defn.v()),
      alpha_(alpha),
      beta_(beta),
      gamma_(gamma),
      x_ji(docs),
      n_k(lda_util::defaultdict<size_t, float>(beta * defn.v()))
      {
        // This page intentionally left blank
}

microscopes::lda::state::state(const model_definition &defn,
      float alpha,
      float beta,
      float gamma,
      size_t initial_dishes,
      const microscopes::lda::nested_vector &docs,
      common::rng_t &rng)
    : state(defn, alpha, beta, gamma, docs) {

    auto dish_pool = microscopes::common::util::range(initial_dishes);

    create_dish(); // Dummy dish
    for (size_t eid = 0; eid < nentities(); ++eid) {
        create_entity(eid);

        auto did = common::util::sample_choice(dish_pool, rng);
        if (did > dishes_.back()){
            did = create_dish();
        }
        create_table(eid, did);
    }
}

microscopes::lda::state::state(const model_definition &defn,
      float alpha,
      float beta,
      float gamma,
      const microscopes::lda::nested_vector &dish_assignments,
      const microscopes::lda::nested_vector &table_assignments,
      const microscopes::lda::nested_vector &docs)
    : state(defn, alpha, beta, gamma, docs) {
        // Explicit initialization constructor for state used for
        // deserialization and testing
        // table_assignment maps words to tables (and should be the same
        //  shape as docs)
        // dish_assignment maps tables to dishes (its outer length should
        //  be the the same as docs. Its inner length one plus the maximum
        //  table index value for the given entity/doc.)

        // Create all the dishes we will need.
        for(auto dish: lda_util::unique_members(dish_assignments)) {
            create_dish(dish);
        }
        for (size_t eid = 0; eid < nentities(); ++eid) {
            create_entity(eid);
            // Create all the tables we will need and assign them to their dish.
            for(auto did: dish_assignments[eid]){
                create_table(eid, did);
            }
            // Assign words to tables.
            for(size_t word_index = 0; word_index < table_assignments[eid].size(); word_index++){
                auto tid  = table_assignments[eid][word_index];
                add_table(eid, tid, word_index);
            }
        }
}

void
microscopes::lda::state::create_entity(size_t eid){
    using_t.push_back(std::vector<size_t>());
    n_jt.push_back(std::vector<size_t>());
    dish_assignments_.push_back(std::vector<size_t>());
    table_assignments_.push_back(std::vector<size_t>(nterms(eid), 0));
    n_jtv.push_back(std::vector< std::map<size_t, size_t>>());
}

microscopes::lda::nested_vector
microscopes::lda::state::assignments() {
    microscopes::lda::nested_vector ret;
    ret.resize(nentities());

    for (size_t eid = 0; eid < nentities(); eid++) {
        ret[eid].resize(table_assignments_[eid].size());
        for (size_t did = 0; did < table_assignments_[eid].size(); did++) {
            auto table = table_assignments_[eid][did];
            ret[eid][did] = dish_assignments_[eid][table];
        }
    }
    return ret;

}

/**
* Returns, for each entity, a map from
* table IDs -> (global) dish assignments
*
*/
microscopes::lda::nested_vector
microscopes::lda::state::dish_assignments() {
    return dish_assignments_;
}

/**
* Returns, for each entity, an assignment vector
* from each word to the (local) table it is assigned to.
*
*/
microscopes::lda::nested_vector
microscopes::lda::state::table_assignments() {
    return table_assignments_;
}

float
microscopes::lda::state::score_assignment() const
{
    return 0;
}

float
microscopes::lda::state::score_data(common::rng_t &rng) const
{
    return 0;
}

std::vector<std::map<size_t, float>>
microscopes::lda::state::word_distribution() {
    // Distribution over words for each topic
    std::vector<std::map<size_t, float>> vec;
    vec.reserve(dishes_.size());
    for (auto k : dishes_) {
        if (k == 0) continue;
        vec.push_back(std::map<size_t, float>());
        for (size_t v = 0; v < V; ++v) {
            vec.back()[v] = n_kv[k].get(v) / n_k.get(k);
        }
    }
    return vec;
}

std::vector<std::vector<float>>
microscopes::lda::state::document_distribution  () {
    // Distribution over topics for each document
    std::vector<std::vector<float>> theta;
    theta.reserve(dish_assignments_.size());
    std::vector<float> am_k(m_k.begin(), m_k.end());
    am_k[0] = gamma_;
    double sum_am_dishes_ = 0;
    for (auto k : dishes_) {
        sum_am_dishes_ += am_k[k];
    }
    for (size_t i = 0; i < am_k.size(); ++i) {
        am_k[i] *= alpha_ / sum_am_dishes_;
    }

    for (size_t j = 0; j < dish_assignments_.size(); j++) {
        std::vector<size_t> &n_jt_ = n_jt[j];
        std::vector<float> p_jk = am_k;
        for (auto t : using_t[j]) {
            if (t == 0) continue;
            size_t k = dish_assignments_[j][t];
            p_jk[k] += n_jt_[t];
        }
        p_jk = lda_util::selectByIndex(p_jk, dishes_);
        lda_util::normalize<float>(p_jk);
        theta.push_back(p_jk);
    }
    return theta;
}

double
microscopes::lda::state::perplexity() {
    std::vector<std::map<size_t, float>> phi = word_distribution();
    std::vector<std::vector<float>> theta = document_distribution();
    phi.insert(phi.begin(), std::map<size_t, float>());
    double log_likelihood = 0;
    size_t N = 0;
    for (size_t eid = 0; eid < nentities(); eid++) {
        for (auto &v : get_entity(eid)) {
            double word_prob = 0;
            for (size_t did = 0; did < dishes_.size(); did++) {
                MICROSCOPES_DCHECK(theta[eid].size() == dishes_.size(), "theta[eid] wrong");
                // Probability that topic of word occurs in document
                // times probability word occurs in topic
                word_prob += theta[eid][did] * phi[did][v];
            }
            log_likelihood -= distributions::fast_log(word_prob);
        }
        N += nterms(eid);
    }

    return exp(log_likelihood / N);
}

// private:

void
microscopes::lda::state::leave_from_dish(size_t j, size_t t) {
    size_t k = dish_assignments_[j][t];
    MICROSCOPES_DCHECK(k > 0, "k < = 0");
    MICROSCOPES_DCHECK(m_k[k] > 0, "m_k[k] <= 0");
    m_k[k] -= 1; // one less table for topic k
    if (m_k[k] == 0) // destroy table
    {
        delete_dish(k);
        dish_assignments_[j][t] = 0;
    }
}

void
microscopes::lda::state::validate_n_k_values() {
    return;
    std::map<size_t, std::tuple<float, float>> values;
    for (auto k : dishes_) {
        float n_kv_sum = 0;
        for (size_t v = 0; v < V; v++) {
            n_kv_sum += n_kv[k].get(v);
        }
        values[k] = std::tuple<float, float>(n_kv_sum, n_k.get(k));
    }
    for (auto kv : values) {
        if (kv.first == 0) continue;
        MICROSCOPES_CHECK(std::abs((std::get<0>(kv.second) - std::get<1>(kv.second))) < 0.01,
                          "n_kv doesn't match n_k");
    }
}

void
microscopes::lda::state::seat_at_dish(size_t j, size_t t, size_t k_new) {
    m_k[k_new] += 1;

    size_t k_old = dish_assignments_[j][t];
    if (k_new != k_old)
    {
        MICROSCOPES_DCHECK(k_new != 0, "k_new is 0");
        dish_assignments_[j][t] = k_new;
        float n_jt_val = n_jt[j][t];

        if (k_old != 0)
        {
            n_k.decr(k_old, n_jt_val);
        }
        n_k.incr(k_new, n_jt_val);
        for (auto kv : n_jtv[j][t]) {
            auto v = kv.first;
            auto n = kv.second;
            MICROSCOPES_DCHECK(v < nwords(), "Word out of bounds");
            if (k_old != 0)
            {
                n_kv[k_old].decr(v, n);
            }
            n_kv[k_new].incr(v, n);
        }
    }
}

void
microscopes::lda::state::add_table(size_t eid, size_t tid, size_t word_index) {
    table_assignments_[eid][word_index] = tid;
    n_jt[eid][tid] += 1;

    size_t k_new = dish_assignments_[eid][tid];
    n_k.incr(k_new, 1);

    size_t v = get_word(eid, word_index);
    MICROSCOPES_DCHECK(v < nwords(), "Word out of bounds");
    n_kv[k_new].incr(v, 1);
    n_jtv[eid][tid][v] += 1;
}

void
microscopes::lda::state::create_dish(size_t k_new){
    while(k_new >= m_k.size())
    {
        m_k.push_back(0);
        n_kv.push_back(lda_util::defaultdict<size_t, float>(beta_));
    }

    dishes_.insert(dishes_.begin() + k_new, k_new);
    n_k.set(k_new, beta_ * V);
    n_kv[k_new] = lda_util::defaultdict<size_t, float>(beta_);
    m_k[k_new] = 0;
}

size_t
microscopes::lda::state::create_dish() {
    size_t k_new = dishes_.size();
    for (size_t i = 0; i < dishes_.size(); ++i)
    {
        if (i != dishes_[i])
        {
            k_new = i;
            break;
        }
    }
    create_dish(k_new);
    return k_new;

}

size_t
microscopes::lda::state::create_table(size_t eid, size_t k_new)
{
    size_t t_new = using_t[eid].size();
    for (size_t i = 0; i < using_t[eid].size(); ++i)
    {
        if (i != using_t[eid][i])
        {
            t_new = i;
            break;
        }
    }
    if (t_new == using_t[eid].size())
    {
        n_jt[eid].push_back(0);
        dish_assignments_[eid].push_back(0);

        n_jtv[eid].push_back(std::map<size_t, size_t>());
    }
    using_t[eid].insert(using_t[eid].begin() + t_new, t_new);
    n_jt[eid][t_new] = 0;
    dish_assignments_[eid][t_new] = k_new;
    if (k_new != 0){
        m_k[k_new] += 1;
    }
    return t_new;
}

void
microscopes::lda::state::remove_table(size_t eid, size_t word_index) {
    size_t tid = table_assignments_[eid][word_index];
    if (tid > 0)
    {
        size_t k = dish_assignments_[eid][tid];
        MICROSCOPES_DCHECK(k > 0, "k <= 0");
        // decrease counters
        size_t v = get_word(eid, word_index);
        MICROSCOPES_DCHECK(v < nwords(), "Word out of bounds");
        n_kv[k].decr(v, 1);
        n_k.decr(k, 1);
        n_jt[eid][tid] -= 1;
        n_jtv[eid][tid][v] -= 1;

        if (n_jt[eid][tid] == 0)
        {
            delete_table(eid, tid);
        }
    }
}

void
microscopes::lda::state::delete_table(size_t eid, size_t tid) {
    size_t k = dish_assignments_[eid][tid];
    lda_util::removeFirst(using_t[eid], tid);
    m_k[k] -= 1;
    MICROSCOPES_DCHECK(m_k[k] >= 0, "m_k[k] < 0");
    if (m_k[k] == 0)
    {
        delete_dish(k);
    }

    // Prune dish assignment vector
    dish_assignments_[eid][tid] = 0;
    while(dish_assignments_[eid].empty() == false)
   {
        if(dish_assignments_[eid].back() == 0){
            dish_assignments_[eid].pop_back();
            n_jt[eid].pop_back();
            n_jtv[eid].pop_back();
        }
        else break;
   }

}

<|endoftext|>


<commit_before>#include "KEngine/Common/StopWatch.hpp"
#include "KEngine/Core/EventManagerImpl.hpp"
#include "KEngine/Log/Log.hpp"

#include <cassert>

namespace ke::priv
{

    EventManagerImpl::~EventManagerImpl(void)
    {
        m_Listeners.clear();
        m_EventQueue.clear();
    }

    bool EventManagerImpl::registerListener(const ke::EventType p_EventType, const ke::EventDelegate & p_Delegate)
    {
        ListenerList & listeners(m_Listeners[p_EventType]);
        for (const DelegateType & listener : listeners)
            if (listener == p_Delegate) // check if already in the list for specified EventType.
            {
                Log::instance()->warn("listener already registered to event type: {}", p_EventType);
                return false;
            }

        listeners.push_back(p_Delegate);
        return true;
    }

    bool EventManagerImpl::deregisterListener(const ke::EventType p_EventType, const ke::EventDelegate & p_EventDelegate)
    {
        if (m_Listeners.find(p_EventType) == m_Listeners.end())
        {
            Log::instance()->warn("no listener is registered to listen to event type: {}", p_EventType);
            return false;
        }
        ListenerList & listeners(m_Listeners[p_EventType]);
        for (ListenerList::const_iterator cit(listeners.begin()); cit != listeners.end(); ++cit)
        {
            if (*cit == p_EventDelegate)
            {
                listeners.erase(cit);
                return true;
            }
        }
        return false;
    }

    bool EventManagerImpl::deregisterAllListeners(const ke::EventType p_EventType)
    {
        if (m_Listeners.find(p_EventType) == m_Listeners.end())
        {
            Log::instance()->warn("no listeners are registered to listen to event type: {}", p_EventType);
            return false;
        }
        m_Listeners[p_EventType].clear();
        return true;
    }

    bool EventManagerImpl::dispatchNow(ke::EventSptr p_Event)
    {
        assert(p_Event->getType() != ke::IEvent::INVALID_EVENT);
        EventListenersMap::iterator it = m_Listeners.find(p_Event->getType());

        if (it == m_Listeners.end())
            return false;

        const ListenerList & listeners = it->second;
        bool handled_event(false);
        for (auto & listener : listeners)
        {
            listener(p_Event);
            handled_event = true;
        }
        return handled_event;
    }

    void EventManagerImpl::queue(ke::EventSptr p_spNewEvent)
    {
        m_ThreadSafeEventQueue.push(p_spNewEvent);
    }

    bool EventManagerImpl::removeEvent(const ke::EventType p_EventType, const bool p_RemoveAllSame)
    {
        bool remove_success(false);
        EventListenersMap::iterator listeners_it(m_Listeners.find(p_EventType));
        if (listeners_it == m_Listeners.end())
            return false;

        EventQueue::iterator it = m_EventQueue.begin();
        while (it != m_EventQueue.end())
        {
            auto it_for_delete = it; ++it; // erase() invalidates iterator. Make a copy and iterate original first.

                                           // different type, move on to next.
            if (p_EventType != (*it_for_delete)->getType()) continue;

            m_EventQueue.erase(it_for_delete); // type match, so remove.
            remove_success = true;

            if (!p_RemoveAllSame) break;
        }
        return remove_success;
    }

    EventProcessResult EventManagerImpl::update(const ke::Time p_ExcutionDurationLimit)
    {
        bool has_duraton_limit = p_ExcutionDurationLimit == ke::Time::Zero ? false : true;

        ke::Time elapsed;
        ke::StopWatch stopwatch; stopwatch.restart();

        ke::EventSptr moving_event_ptr;
        while (m_ThreadSafeEventQueue.poll(moving_event_ptr))
            m_EventQueue.push_back(moving_event_ptr);

        ke::EventSptr event_ptr;
        while (!m_EventQueue.empty())
        {
            elapsed += stopwatch.getElapsed(); stopwatch.restart();
            if (has_duraton_limit && elapsed >= p_ExcutionDurationLimit) // if elapsed time if duration limit setted.
                break;

            event_ptr = m_EventQueue.front(); m_EventQueue.pop_front();

            auto listeners_it = m_Listeners.find(event_ptr->getType());
            if (listeners_it == m_Listeners.end()) // no listeners registered for this type.
                continue;

            ListenerList & list(listeners_it->second);
            for (auto & listener : list)
                listener(event_ptr);    // call delegate
        }

        if (m_ThreadSafeEventQueue.isEmpty())
            return ke::EventProcessResult::ALL_EVENTS_PROCESSED;
        return ke::EventProcessResult::SOME_EVENTS_PROCESSED;
    }

}
<commit_msg>renamed parameter<commit_after>#include "KEngine/Common/StopWatch.hpp"
#include "KEngine/Core/EventManagerImpl.hpp"
#include "KEngine/Log/Log.hpp"

#include <cassert>

namespace ke::priv
{

    EventManagerImpl::~EventManagerImpl(void)
    {
        m_Listeners.clear();
        m_EventQueue.clear();
    }

    bool EventManagerImpl::registerListener(const ke::EventType p_EventType, const ke::EventDelegate & p_Delegate)
    {
        ListenerList & listeners(m_Listeners[p_EventType]);
        for (const DelegateType & listener : listeners)
            if (listener == p_Delegate) // check if already in the list for specified EventType.
            {
                Log::instance()->warn("listener already registered to event type: {}", p_EventType);
                return false;
            }

        listeners.push_back(p_Delegate);
        return true;
    }

    bool EventManagerImpl::deregisterListener(const ke::EventType p_EventType, const ke::EventDelegate & p_Delegate)
    {
        if (m_Listeners.find(p_EventType) == m_Listeners.end())
        {
            Log::instance()->warn("no listener is registered to listen to event type: {}", p_EventType);
            return false;
        }
        ListenerList & listeners(m_Listeners[p_EventType]);
        for (ListenerList::const_iterator cit(listeners.begin()); cit != listeners.end(); ++cit)
        {
            if (*cit == p_Delegate)
            {
                listeners.erase(cit);
                return true;
            }
        }
        return false;
    }

    bool EventManagerImpl::deregisterAllListeners(const ke::EventType p_EventType)
    {
        if (m_Listeners.find(p_EventType) == m_Listeners.end())
        {
            Log::instance()->warn("no listeners are registered to listen to event type: {}", p_EventType);
            return false;
        }
        m_Listeners[p_EventType].clear();
        return true;
    }

    bool EventManagerImpl::dispatchNow(ke::EventSptr p_Event)
    {
        assert(p_Event->getType() != ke::IEvent::INVALID_EVENT);
        EventListenersMap::iterator it = m_Listeners.find(p_Event->getType());

        if (it == m_Listeners.end())
            return false;

        const ListenerList & listeners = it->second;
        bool handled_event(false);
        for (auto & listener : listeners)
        {
            listener(p_Event);
            handled_event = true;
        }
        return handled_event;
    }

    void EventManagerImpl::queue(ke::EventSptr p_spNewEvent)
    {
        m_ThreadSafeEventQueue.push(p_spNewEvent);
    }

    bool EventManagerImpl::removeEvent(const ke::EventType p_EventType, const bool p_RemoveAllSame)
    {
        bool remove_success(false);
        EventListenersMap::iterator listeners_it(m_Listeners.find(p_EventType));
        if (listeners_it == m_Listeners.end())
            return false;

        EventQueue::iterator it = m_EventQueue.begin();
        while (it != m_EventQueue.end())
        {
            auto it_for_delete = it; ++it; // erase() invalidates iterator. Make a copy and iterate original first.

                                           // different type, move on to next.
            if (p_EventType != (*it_for_delete)->getType()) continue;

            m_EventQueue.erase(it_for_delete); // type match, so remove.
            remove_success = true;

            if (!p_RemoveAllSame) break;
        }
        return remove_success;
    }

    EventProcessResult EventManagerImpl::update(const ke::Time p_ExcutionDurationLimit)
    {
        bool has_duraton_limit = p_ExcutionDurationLimit == ke::Time::Zero ? false : true;

        ke::Time elapsed;
        ke::StopWatch stopwatch; stopwatch.restart();

        ke::EventSptr moving_event_ptr;
        while (m_ThreadSafeEventQueue.poll(moving_event_ptr))
            m_EventQueue.push_back(moving_event_ptr);

        ke::EventSptr event_ptr;
        while (!m_EventQueue.empty())
        {
            elapsed += stopwatch.getElapsed(); stopwatch.restart();
            if (has_duraton_limit && elapsed >= p_ExcutionDurationLimit) // if elapsed time if duration limit setted.
                break;

            event_ptr = m_EventQueue.front(); m_EventQueue.pop_front();

            auto listeners_it = m_Listeners.find(event_ptr->getType());
            if (listeners_it == m_Listeners.end()) // no listeners registered for this type.
                continue;

            ListenerList & list(listeners_it->second);
            for (auto & listener : list)
                listener(event_ptr);    // call delegate
        }

        if (m_ThreadSafeEventQueue.isEmpty())
            return ke::EventProcessResult::ALL_EVENTS_PROCESSED;
        return ke::EventProcessResult::SOME_EVENTS_PROCESSED;
    }

}
<|endoftext|>


<commit_before>#include <assert.h>

#include <algorithm>
#include <cmath>
#include <iostream>
#include <iomanip>
#include <set>

#include <ftl/ftl.h>

#include "timestamp.h"

// -----------------------------------------------------------------------------
// -- Helper Functions
// -----------------------------------------------------------------------------
template <typename T>
T sqrt_int(T num) {
  return static_cast<T>(std::sqrt(num + 0.99));
}

uint64_t smallest_prime_factor(uint64_t num) {
  return ftl::range(2llu, sqrt_int(num) + 1)
      .filter([num](let p){ return (num % p) == 0; })
      .head()
      .value_or(num);
}

uint64_t largest_prime_factor(uint64_t num) {
  let p = smallest_prime_factor(num);
  return p == num ? p : largest_prime_factor(num / p);
}

uint64_t is_prime(uint64_t num) {
  return num == smallest_prime_factor(num);
};

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------

// Find the sum of all the multiples of 3 or 5 below 1000.
int problem1() {
  return ftl::range(1000)
      .filter([](let x){ return x % 3 == 0 || x % 5 == 0; })
      .sum();
}

// By considering the terms in the Fibonacci sequence whose values do not exceed
// four million, find the sum of the even-valued terms.
int problem2() {
  return ftl::unfold(std::make_tuple(1, 1), [](let x){
          return std::make_tuple(std::get<1>(x),
                                 std::get<0>(x) + std::get<1>(x));
      })
      .map([](let x){ return std::get<0>(x); })
      .take_while([](let x){ return x < 4'000'000; })
      .filter([](let x){ return x % 2 == 0; })
      .sum();
}

// What is the largest prime factor of the number 600851475143
uint64_t problem3() {
  return largest_prime_factor(600851475143llu);
}

// Find the difference between the sum of the squares of the first one hundred
// natural numbers and the square of the sum.
uint64_t problem6() {
  let n = 100;
  let square = [](let x){ return x * x; };
  let sum_squares = ftl::range(1, n + 1).map(square).sum();
  let square_sum = square(ftl::range(1, n + 1).sum());
  return square_sum - sum_squares;
}

// What is the 10'001st prime number?
uint64_t problem7() {
  return ftl::iota(2llu).filter(is_prime).take(10'001).tail().value();
}

// There exists exactly one Pythagorean triplet for which a + b + c = 1000.
// Find the product abc.
uint32_t problem9() {
  let n = 1000;
  return ftl::range(1, n / 2).map([](let a){
      return ftl::range(1, a).map([a](let b){
          return std::make_tuple(a, b);
      });
  })
  .flat_map([n](let ab){
      return std::tuple_cat(ab,
          std::make_tuple(n - std::get<0>(ab) - std::get<1>(ab)));
  })
  .filter([](let abc) {
      let a = std::get<0>(abc);
      let b = std::get<1>(abc);
      let c = std::get<2>(abc);
      return a * a + b * b ==  c * c;
  })
  .map([](let abc){
      return std::get<0>(abc) * std::get<1>(abc) * std::get<2>(abc);
  })
  .head()
  .value();
}

// Find the sum of all the primes below two million.
uint64_t problem10() {
  return ftl::range(2, 2'000'000).filter(is_prime).sum<uint64_t>();
}

// What is the value of the first triangle number to have over five hundred
// divisors?
uint64_t problem12() {
  let num_divisors = [](let n) {
      let sqrtn = sqrt_int(n);
      return ftl::range(1, sqrtn)
          .filter([n](let i) { return n % i == 0; })
          .map([](let _) { return 1; })
          .sum() * 2 + (sqrtn * sqrtn == n ? 1 : 0);
  };
  return ftl::iota(1)
     .map([](let x) { return x * (x + 1) / 2; })
     .filter([&num_divisors](let x){ return num_divisors(x) > 500; })
     .head().value();
}

uint64_t problem14() {
  let chain_length = [](let n){
    return ftl::unfold(n,
        [](let i){
            if (i == 1) {
              return ftl::optional<uint64_t>();
            } else if (i % 2 == 0) {
              return ftl::make_optional(i / 2);
            } else {
              return ftl::make_optional(3 * i + 1);
            }
        })
        .map([](let _){ return 1; })
        .sum();
  };
  return std::get<0>(ftl::range(1llu, 1'000'000llu)
      .map([chain_length](let i){
        return std::make_tuple(i, chain_length(i));
      })
      .reduce(std::make_tuple(0llu, 0), [](let acc, let val){
        if (std::get<1>(acc) < std::get<1>(val)) {
          return val;
        } else {
          return acc;
        }
      }));
}

// Find the sum of all the positive integers which cannot be written as the sum
// of two abundant numbers.
uint64_t problem23() {
  let max_num = 28123;

  let is_abundant_impl = [](let n){
      let sqrtn = sqrt_int(n);
      let sum_divisors = ftl::range(1, sqrtn + 1)
          .filter([n](let i){ return n % i == 0; })
          .map([n](let i){ return i == 1 || i * i == n ? i : i + n / i; })
          .sum();
      return sum_divisors > n;
  };

  let is_abundant = ftl::memoize<decltype(is_abundant_impl), int>(
      is_abundant_impl);

  let abundants = ftl::range(1, max_num + 1).filter(is_abundant).eval();

  let is_sum_abundants = [&is_abundant, &abundants](let n){
      return abundants
          .filter([n](let k){ return k < n; })
          .filter([n, &is_abundant](let k){ return is_abundant(n - k); })
          .any();
  };

  return ftl::range(1, max_num + 1)
      .filter([&is_sum_abundants](let i){ return !is_sum_abundants(i); })
      .sum();
}

template <typename Func>
void do_run(const std::string &name, const Func &f) {
  uint64_t t_start = timestamp_ms();
  let res = f();
  uint64_t t_stop = timestamp_ms();
  std::cout << "| "
            << std::setw(10) << std::left << name << " | "
            << std::setw(12) << std::right << res << " | "
            << std::setw(5) << t_stop - t_start << "ms"
            << " |"
            << std::endl;
}

#define STRINGIFY(x) #x
#define TOSTRING(x)  STRINGIFY(x)
#define RUN(f) do_run(TOSTRING(f), (f))

int main() {
  const char* spacing = "---------------------------------------";
  const char* title =   "| Project Euler examples              |";

  std::cout << spacing << std::endl
            << title << std::endl
            << spacing << std::endl;

  RUN(problem1);
  RUN(problem2);
  RUN(problem3);
  RUN(problem6);
  RUN(problem7);
  RUN(problem9);
  RUN(problem10);
  RUN(problem12);
  RUN(problem14);
  RUN(problem23);

  std::cout << spacing << std::endl;
}

<commit_msg>fixed indent<commit_after>#include <assert.h>

#include <algorithm>
#include <cmath>
#include <iostream>
#include <iomanip>
#include <set>

#include <ftl/ftl.h>

#include "timestamp.h"

// -----------------------------------------------------------------------------
// -- Helper Functions
// -----------------------------------------------------------------------------
template <typename T>
T sqrt_int(T num) {
  return static_cast<T>(std::sqrt(num + 0.99));
}

uint64_t smallest_prime_factor(uint64_t num) {
  return ftl::range(2llu, sqrt_int(num) + 1)
      .filter([num](let p){ return (num % p) == 0; })
      .head()
      .value_or(num);
}

uint64_t largest_prime_factor(uint64_t num) {
  let p = smallest_prime_factor(num);
  return p == num ? p : largest_prime_factor(num / p);
}

uint64_t is_prime(uint64_t num) {
  return num == smallest_prime_factor(num);
};

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------

// Find the sum of all the multiples of 3 or 5 below 1000.
int problem1() {
  return ftl::range(1000)
      .filter([](let x){ return x % 3 == 0 || x % 5 == 0; })
      .sum();
}

// By considering the terms in the Fibonacci sequence whose values do not exceed
// four million, find the sum of the even-valued terms.
int problem2() {
  return ftl::unfold(std::make_tuple(1, 1), [](let x){
          return std::make_tuple(std::get<1>(x),
                                 std::get<0>(x) + std::get<1>(x));
      })
      .map([](let x){ return std::get<0>(x); })
      .take_while([](let x){ return x < 4'000'000; })
      .filter([](let x){ return x % 2 == 0; })
      .sum();
}

// What is the largest prime factor of the number 600851475143
uint64_t problem3() {
  return largest_prime_factor(600851475143llu);
}

// Find the difference between the sum of the squares of the first one hundred
// natural numbers and the square of the sum.
uint64_t problem6() {
  let n = 100;
  let square = [](let x){ return x * x; };
  let sum_squares = ftl::range(1, n + 1).map(square).sum();
  let square_sum = square(ftl::range(1, n + 1).sum());
  return square_sum - sum_squares;
}

// What is the 10'001st prime number?
uint64_t problem7() {
  return ftl::iota(2llu).filter(is_prime).take(10'001).tail().value();
}

// There exists exactly one Pythagorean triplet for which a + b + c = 1000.
// Find the product abc.
uint32_t problem9() {
  let n = 1000;
  return ftl::range(1, n / 2).map([](let a){
          return ftl::range(1, a).map([a](let b){
              return std::make_tuple(a, b);
          });
      })
      .flat_map([n](let ab){
          return std::tuple_cat(ab,
              std::make_tuple(n - std::get<0>(ab) - std::get<1>(ab)));
      })
      .filter([](let abc) {
          let a = std::get<0>(abc);
          let b = std::get<1>(abc);
          let c = std::get<2>(abc);
          return a * a + b * b ==  c * c;
      })
      .map([](let abc){
          return std::get<0>(abc) * std::get<1>(abc) * std::get<2>(abc);
      })
      .head()
      .value();
}

// Find the sum of all the primes below two million.
uint64_t problem10() {
  return ftl::range(2, 2'000'000).filter(is_prime).sum<uint64_t>();
}

// What is the value of the first triangle number to have over five hundred
// divisors?
uint64_t problem12() {
  let num_divisors = [](let n) {
      let sqrtn = sqrt_int(n);
      return ftl::range(1, sqrtn)
          .filter([n](let i) { return n % i == 0; })
          .map([](let _) { return 1; })
          .sum() * 2 + (sqrtn * sqrtn == n ? 1 : 0);
  };
  return ftl::iota(1)
     .map([](let x) { return x * (x + 1) / 2; })
     .filter([&num_divisors](let x){ return num_divisors(x) > 500; })
     .head().value();
}

uint64_t problem14() {
  let chain_length = [](let n){
    return ftl::unfold(n,
        [](let i){
            if (i == 1) {
              return ftl::optional<uint64_t>();
            } else if (i % 2 == 0) {
              return ftl::make_optional(i / 2);
            } else {
              return ftl::make_optional(3 * i + 1);
            }
        })
        .map([](let _){ return 1; })
        .sum();
  };
  return std::get<0>(ftl::range(1llu, 1'000'000llu)
      .map([chain_length](let i){
        return std::make_tuple(i, chain_length(i));
      })
      .reduce(std::make_tuple(0llu, 0), [](let acc, let val){
        if (std::get<1>(acc) < std::get<1>(val)) {
          return val;
        } else {
          return acc;
        }
      }));
}

// Find the sum of all the positive integers which cannot be written as the sum
// of two abundant numbers.
uint64_t problem23() {
  let max_num = 28123;

  let is_abundant_impl = [](let n){
      let sqrtn = sqrt_int(n);
      let sum_divisors = ftl::range(1, sqrtn + 1)
          .filter([n](let i){ return n % i == 0; })
          .map([n](let i){ return i == 1 || i * i == n ? i : i + n / i; })
          .sum();
      return sum_divisors > n;
  };

  let is_abundant = ftl::memoize<decltype(is_abundant_impl), int>(
      is_abundant_impl);

  let abundants = ftl::range(1, max_num + 1).filter(is_abundant).eval();

  let is_sum_abundants = [&is_abundant, &abundants](let n){
      return abundants
          .filter([n](let k){ return k < n; })
          .filter([n, &is_abundant](let k){ return is_abundant(n - k); })
          .any();
  };

  return ftl::range(1, max_num + 1)
      .filter([&is_sum_abundants](let i){ return !is_sum_abundants(i); })
      .sum();
}

template <typename Func>
void do_run(const std::string &name, const Func &f) {
  uint64_t t_start = timestamp_ms();
  let res = f();
  uint64_t t_stop = timestamp_ms();
  std::cout << "| "
            << std::setw(10) << std::left << name << " | "
            << std::setw(12) << std::right << res << " | "
            << std::setw(5) << t_stop - t_start << "ms"
            << " |"
            << std::endl;
}

#define STRINGIFY(x) #x
#define TOSTRING(x)  STRINGIFY(x)
#define RUN(f) do_run(TOSTRING(f), (f))

int main() {
  const char* spacing = "---------------------------------------";
  const char* title =   "| Project Euler examples              |";

  std::cout << spacing << std::endl
            << title << std::endl
            << spacing << std::endl;

  RUN(problem1);
  RUN(problem2);
  RUN(problem3);
  RUN(problem6);
  RUN(problem7);
  RUN(problem9);
  RUN(problem10);
  RUN(problem12);
  RUN(problem14);
  RUN(problem23);

  std::cout << spacing << std::endl;
}

<|endoftext|>


<commit_before>// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.

#ifndef MFEM_TEMPLATE_CONFIG
#define MFEM_TEMPLATE_CONFIG

// the main MFEM config header
#include "config.hpp"

// --- MFEM_STATIC_ASSERT
#if (__cplusplus >= 201103L)
#define MFEM_STATIC_ASSERT(cond, msg) static_assert((cond), msg)
#else
#define MFEM_STATIC_ASSERT(cond, msg) if (cond) { }
#endif

// --- MFEM_ALWAYS_INLINE
#if !defined(MFEM_DEBUG) && (defined(__GNUC__) || defined(__clang__))
#define MFEM_ALWAYS_INLINE __attribute__((always_inline))
#else
#define MFEM_ALWAYS_INLINE
#endif

// --- MFEM_VECTORIZE_LOOP (disabled)
#if (__cplusplus >= 201103L) && !defined(MFEM_DEBUG) && defined(__GNUC__)
//#define MFEM_VECTORIZE_LOOP _Pragma("GCC ivdep")
#define MFEM_VECTORIZE_LOOP
#else
#define MFEM_VECTORIZE_LOOP
#endif

// --- MFEM_ALIGN_AS
#if (__cplusplus >= 201103L)
#define MFEM_ALIGN_AS(bytes) alignas(bytes)
#elif !defined(MFEM_DEBUG) && (defined(__GNUC__) || defined(__clang__))
#define MFEM_ALIGN_AS(bytes) __attribute__ ((aligned (bytes)))
#else
#define MFEM_ALIGN_AS(bytes)
#endif

// --- POSIX MEMALIGN
#ifdef _WIN32
#define MFEM_POSIX_MEMALIGN(p,a,s) (((*(p))=_aligned_malloc((s),(a))),*(p)?0:errno)
#define MFEM_POSIX_MEMALIGN_FREE _aligned_free
#else
#define MFEM_POSIX_MEMALIGN posix_memalign
#define MFEM_POSIX_MEMALIGN_FREE free
#endif

// --- AutoSIMD or intrinsics
#ifndef MFEM_USE_SIMD
#include "simd/auto.hpp"
#else
#if defined(__VSX__)
#include "simd/vsx.hpp"
#elif defined (__bgq__)
#include "simd/qpx.hpp"
#elif defined(__x86_64__)
#include "simd/x86.hpp"
#else
#error Unknown SIMD architecture
#endif
#endif

// --- Default SIMD and BLOCK sizes
#ifdef _WIN32
#define MFEM_SIMD_DEFAULT_SIZE 8
#define MFEM_TEMPLATE_BLOCK_DEFAULT_SIZE 1
#else
#define MFEM_SIMD_DEFAULT_SIZE 32
#define MFEM_TEMPLATE_BLOCK_DEFAULT_SIZE 4
#endif

// --- SIMD and BLOCK sizes
#ifndef MFEM_USE_SIMD
#define MFEM_SIMD_SIZE MFEM_SIMD_DEFAULT_SIZE
#define MFEM_TEMPLATE_BLOCK_SIZE MFEM_TEMPLATE_BLOCK_DEFAULT_SIZE
#else
#ifdef __VSX__
#define MFEM_SIMD_SIZE 16
#define MFEM_TEMPLATE_BLOCK_SIZE 2
#else
#define MFEM_SIMD_SIZE MFEM_SIMD_DEFAULT_SIZE
#define MFEM_TEMPLATE_BLOCK_SIZE MFEM_TEMPLATE_BLOCK_DEFAULT_SIZE
#endif
#endif

template<typename complex_t, typename real_t, bool simd>
struct AutoImplTraits
{
   static const int block_size = MFEM_TEMPLATE_BLOCK_SIZE;

   static const int align_size = MFEM_SIMD_SIZE; // in bytes

   static const int batch_size = 1;

   static const int simd_size = simd?(MFEM_SIMD_SIZE/sizeof(complex_t)):1;

   static const int valign_size = simd?simd_size:1;

   typedef AutoSIMD<complex_t,simd_size,valign_size> vcomplex_t;
   typedef AutoSIMD<   real_t,simd_size,valign_size> vreal_t;
#ifndef MFEM_USE_SIMD
   typedef AutoSIMD<      int,simd_size,valign_size> vint_t;
#endif // MFEM_USE_SIMD
};

#define MFEM_TEMPLATE_ENABLE_SERIALIZE

// #define MFEM_TEMPLATE_ELTRANS_HAS_NODE_DOFS
// #define MFEM_TEMPLATE_ELTRANS_RESULT_HAS_NODES
// #define MFEM_TEMPLATE_FIELD_EVAL_DATA_HAS_DOFS
#define MFEM_TEMPLATE_INTRULE_COEFF_PRECOMP

// derived macros
#define MFEM_ROUNDUP(val,base) ((((val)+(base)-1)/(base))*(base))
#define MFEM_ALIGN_SIZE(size,type) \
   MFEM_ROUNDUP(size,(MFEM_SIMD_SIZE)/sizeof(type))

#ifdef MFEM_COUNT_FLOPS
namespace mfem
{
namespace internal
{
extern long long flop_count;
}
}
#define MFEM_FLOPS_RESET() (mfem::internal::flop_count = 0)
#define MFEM_FLOPS_ADD(cnt) (mfem::internal::flop_count += (cnt))
#define MFEM_FLOPS_GET() (mfem::internal::flop_count)
#else
#define MFEM_FLOPS_RESET()
#define MFEM_FLOPS_ADD(cnt)
#define MFEM_FLOPS_GET() (0)
#endif

#endif // MFEM_TEMPLATE_CONFIG
<commit_msg>VSX tconfig logic<commit_after>// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.

#ifndef MFEM_TEMPLATE_CONFIG
#define MFEM_TEMPLATE_CONFIG

// the main MFEM config header
#include "config.hpp"

// --- MFEM_STATIC_ASSERT
#if (__cplusplus >= 201103L)
#define MFEM_STATIC_ASSERT(cond, msg) static_assert((cond), msg)
#else
#define MFEM_STATIC_ASSERT(cond, msg) if (cond) { }
#endif

// --- MFEM_ALWAYS_INLINE
#if !defined(MFEM_DEBUG) && (defined(__GNUC__) || defined(__clang__))
#define MFEM_ALWAYS_INLINE __attribute__((always_inline))
#else
#define MFEM_ALWAYS_INLINE
#endif

// --- MFEM_VECTORIZE_LOOP (disabled)
#if (__cplusplus >= 201103L) && !defined(MFEM_DEBUG) && defined(__GNUC__)
//#define MFEM_VECTORIZE_LOOP _Pragma("GCC ivdep")
#define MFEM_VECTORIZE_LOOP
#else
#define MFEM_VECTORIZE_LOOP
#endif

// --- MFEM_ALIGN_AS
#if (__cplusplus >= 201103L)
#define MFEM_ALIGN_AS(bytes) alignas(bytes)
#elif !defined(MFEM_DEBUG) && (defined(__GNUC__) || defined(__clang__))
#define MFEM_ALIGN_AS(bytes) __attribute__ ((aligned (bytes)))
#else
#define MFEM_ALIGN_AS(bytes)
#endif

// --- POSIX MEMALIGN
#ifdef _WIN32
#define MFEM_POSIX_MEMALIGN(p,a,s) (((*(p))=_aligned_malloc((s),(a))),*(p)?0:errno)
#define MFEM_POSIX_MEMALIGN_FREE _aligned_free
#else
#define MFEM_POSIX_MEMALIGN posix_memalign
#define MFEM_POSIX_MEMALIGN_FREE free
#endif

// --- AutoSIMD or intrinsics
#ifndef MFEM_USE_SIMD
#include "simd/auto.hpp"
#else
#if defined(__VSX__)
#include "simd/vsx.hpp"
#elif defined (__bgq__)
#include "simd/qpx.hpp"
#elif defined(__x86_64__)
#include "simd/x86.hpp"
#else
#error Unknown SIMD architecture
#endif
#endif

// --- SIMD and BLOCK sizes
#if defined(_WIN32)
#define MFEM_SIMD_SIZE 8
#define MFEM_TEMPLATE_BLOCK_SIZE 1
#elif defined(__VSX__)
#define MFEM_SIMD_SIZE 16
#define MFEM_TEMPLATE_BLOCK_SIZE 2
#elif defined(__x86_64__)
#define MFEM_SIMD_SIZE 32
#define MFEM_TEMPLATE_BLOCK_SIZE 4
#else
#error Unknown SIMD architecture
#endif

template<typename complex_t, typename real_t, bool simd>
struct AutoImplTraits
{
   static const int block_size = MFEM_TEMPLATE_BLOCK_SIZE;

   static const int align_size = MFEM_SIMD_SIZE; // in bytes

   static const int batch_size = 1;

   static const int simd_size = simd?(MFEM_SIMD_SIZE/sizeof(complex_t)):1;

   static const int valign_size = simd?simd_size:1;

   typedef AutoSIMD<complex_t,simd_size,valign_size> vcomplex_t;
   typedef AutoSIMD<   real_t,simd_size,valign_size> vreal_t;
#ifndef MFEM_USE_SIMD
   typedef AutoSIMD<      int,simd_size,valign_size> vint_t;
#endif // MFEM_USE_SIMD
};

#define MFEM_TEMPLATE_ENABLE_SERIALIZE

// #define MFEM_TEMPLATE_ELTRANS_HAS_NODE_DOFS
// #define MFEM_TEMPLATE_ELTRANS_RESULT_HAS_NODES
// #define MFEM_TEMPLATE_FIELD_EVAL_DATA_HAS_DOFS
#define MFEM_TEMPLATE_INTRULE_COEFF_PRECOMP

// derived macros
#define MFEM_ROUNDUP(val,base) ((((val)+(base)-1)/(base))*(base))
#define MFEM_ALIGN_SIZE(size,type) \
   MFEM_ROUNDUP(size,(MFEM_SIMD_SIZE)/sizeof(type))

#ifdef MFEM_COUNT_FLOPS
namespace mfem
{
namespace internal
{
extern long long flop_count;
}
}
#define MFEM_FLOPS_RESET() (mfem::internal::flop_count = 0)
#define MFEM_FLOPS_ADD(cnt) (mfem::internal::flop_count += (cnt))
#define MFEM_FLOPS_GET() (mfem::internal::flop_count)
#else
#define MFEM_FLOPS_RESET()
#define MFEM_FLOPS_ADD(cnt)
#define MFEM_FLOPS_GET() (0)
#endif

#endif // MFEM_TEMPLATE_CONFIG
<|endoftext|>


<commit_before>using namespace GeFiCa;
//Compare numerical result to analytic calculation for 1D spherical detector
void compare2analytic()
{
   // configure detector
   Sphere1D *num=new Sphere1D;
   num->InnerR=0.3*cm;
   num->OuterR=1*cm;
   num->SetAverageImpurity(3e9/cm3);
   num->V0=900*volt;
   num->V1=0*volt;
   num->Dump();
   cout<<"press any key to continue"<<endl; cin.get();

   // make a copy of the detector configuration
   Sphere1D *ana = (Sphere1D*) num->Clone("ana");

   // calculate potential using SOR method
   num->CalculatePotential(kSOR2);

   // fill grid with analytic result
   ana->CalculatePotential(kAnalytic);

   // prepare drawing style
   gROOT->SetStyle("Plain"); // pick up a good drawing style to modify
   gStyle->SetLegendBorderSize(0);
   gStyle->SetLegendFont(132);
   gStyle->SetLabelFont(132,"XY");
   gStyle->SetTitleFont(132,"XY");
   gStyle->SetLabelSize(0.05,"XY");
   gStyle->SetTitleSize(0.05,"XY");
   gStyle->SetPadRightMargin(0.01);
   gStyle->SetPadLeftMargin(0.12);
   gStyle->SetPadTopMargin(0.02);

   // generate graphics
   TTree *tn = num->GetTree();
   tn->Draw("v:c1");
   TGraph *gn = new TGraph(tn->GetSelectedRows(), tn->GetV2(), tn->GetV1());

   TTree *ta = ana->GetTree();
   ta->Draw("v:c1");
   TGraph *ga = new TGraph(ta->GetSelectedRows(), ta->GetV2(), ta->GetV1());

   // compare numerical result to analytic calculation
   gn->SetMarkerColor(kBlue);
   gn->SetMarkerStyle(kCircle);
   gn->SetMarkerSize(0.8);
   gn->SetTitle(";Radius [cm];Potential [V]");
   gn->GetXaxis()->SetRangeUser(0,3);
   gn->GetYaxis()->SetRangeUser(0,900);
   gn->Draw("ap");

   ga->SetLineColor(kRed);
   ga->Draw("l");

   TLegend *l = new TLegend(0.6,0.6,0.8,0.8);
   l->AddEntry(ga,"Analytic","l");
   l->AddEntry(gn,"SOR2","p");
   l->Draw();

   gPad->Print("s1d.png");
}
<commit_msg>improved title of x-axis<commit_after>using namespace GeFiCa;
//Compare numerical result to analytic calculation for 1D spherical detector
void compare2analytic()
{
   // configure detector
   Sphere1D *num=new Sphere1D;
   num->InnerR=0.3*cm;
   num->OuterR=1*cm;
   num->SetAverageImpurity(3e9/cm3);
   num->V0=900*volt;
   num->V1=0*volt;
   num->Dump();
   cout<<"press any key to continue"<<endl; cin.get();

   // make a copy of the detector configuration
   Sphere1D *ana = (Sphere1D*) num->Clone("ana");

   // calculate potential using SOR method
   num->CalculatePotential(kSOR2);

   // fill grid with analytic result
   ana->CalculatePotential(kAnalytic);

   // generate graphics
   gStyle->SetPadRightMargin(0.01);
   TTree *tn = num->GetTree();
   tn->Draw("v:c1","","goff");
   TGraph *gn = new TGraph(tn->GetSelectedRows(), tn->GetV2(), tn->GetV1());
   TTree *ta = ana->GetTree();
   ta->Draw("v:c1","","goff");
   TGraph *ga = new TGraph(ta->GetSelectedRows(), ta->GetV2(), ta->GetV1());

   // compare numerical result to analytic calculation
   gn->SetMarkerColor(kBlue);
   gn->SetMarkerStyle(kCircle);
   gn->SetMarkerSize(0.8);
   gn->SetTitle(";Radial position [cm];Potential [V]");
   gn->GetXaxis()->SetRangeUser(0,1);
   gn->GetYaxis()->SetRangeUser(0,900);
   gn->Draw("ap");

   ga->SetLineColor(kRed);
   ga->Draw("l");

   TLegend *l = new TLegend(0.6,0.6,0.8,0.8);
   l->AddEntry(ga,"Analytic","l");
   l->AddEntry(gn,"SOR","p");
   l->Draw();

   gPad->Print("s1d.png");
}
<|endoftext|>


<commit_before>#pragma once

#include <fmt/format.h>
#include <plog/Log.h>

#include "util/typedefs.hpp"
#include "filesystem.hpp"

#include "core/ui/canvas.hpp"

namespace top1::ui::drawing {

  const uint WIDTH = 320;
  const uint HEIGHT = 240;

  namespace Colours {

    const Colour Black     = Colour(0x000000);

    const MainColour White = {0xFFFFFF, 0x646464};
    const MainColour Red   = {0xFF2A2A, 0x6E0C0C};
    const MainColour Green = {0x5ECF3E, 0x0C6E0C};
    const MainColour Blue  = {0x0A7CFF, 0x0C0C6E};

    const Colour Gray60    = 0x999999;
    const Colour Gray70    = 0xB2B2B2;

  } // Colours

  namespace Fonts {
    inline Font Light;
    inline Font Norm;
    inline Font Bold;

    inline fs::path font_dir {"data/fonts"};
  }

  inline void initUtils(Canvas &canvas) {
    Fonts::Light = Font(canvas, "TOP-1 Light", Fonts::font_dir / "TOP-1" / "TOP-1.ttf");
    if (!Fonts::Light.valid()) {
      LOGE << "Invalid font: " << Fonts::Light.name;
    }
    Fonts::Norm = Font(canvas, "TOP-1 Regular", Fonts::font_dir / "TOP-1" / "TOP-1.ttf");
    if (!Fonts::Norm.valid()) {
      LOGE << "Invalid font: " << Fonts::Norm.name;
    }
    Fonts::Bold = Font(canvas, "TOP-1 Bold", Fonts::font_dir / "TOP-1" / "TOP-1.ttf");
    if (!Fonts::Bold.valid()) {
      LOGE << "Invalid font: " << Fonts::Bold.name;
    }
  }

} // ui::drawing
<commit_msg>Register the new fonts<commit_after>#pragma once

#include <fmt/format.h>
#include <plog/Log.h>

#include "util/typedefs.hpp"
#include "filesystem.hpp"

#include "core/ui/canvas.hpp"

namespace top1::ui::drawing {

  const uint WIDTH = 320;
  const uint HEIGHT = 240;

  namespace Colours {

    const Colour Black     = Colour(0x000000);

    const MainColour White = {0xFFFFFF, 0x646464};
    const MainColour Red   = {0xFF2A2A, 0x6E0C0C};
    const MainColour Green = {0x5ECF3E, 0x0C6E0C};
    const MainColour Blue  = {0x0A7CFF, 0x0C0C6E};

    const Colour Gray60    = 0x999999;
    const Colour Gray70    = 0xB2B2B2;

  } // Colours

  namespace Fonts {
    inline Font Light;
    inline Font Norm;
    inline Font Bold;
    inline Font SemiBold;
    inline Font Mono;

    inline fs::path font_dir {"data/fonts"};
    inline void loadFont(Canvas& ctx, Font& font, const std::string& name)
    {
      auto path = Fonts::font_dir / (name + ".ttf");
      font = Font(ctx, name, path);
      if (!Fonts::Light.valid()) {
        LOGE << "Invalid font: " << Fonts::Light.name << "";
        if (!fs::exists(path)) {
          LOGE << "Font file not found: " << path.c_str();
        }
      }
    }
  }

  inline void initUtils(Canvas& ctx) {
    Fonts::loadFont(ctx, Fonts::Light, "TOP-1-Light");
    Fonts::loadFont(ctx, Fonts::Norm, "TOP-1-Regular");
    Fonts::loadFont(ctx, Fonts::Bold, "TOP-1-Bold");
    Fonts::loadFont(ctx, Fonts::SemiBold, "TOP-1-SemiBold");
    Fonts::loadFont(ctx, Fonts::Mono, "TOP-1-Mono-Regular");
  }

} // ui::drawing
<|endoftext|>


<commit_before>#include "StdAfx.h"

#include "CapsuleShape.h"

CapsuleShape::CapsuleShape(btCapsuleShape* shape)
: ConvexInternalShape(shape)
{
}

CapsuleShape::CapsuleShape(btScalar radius, btScalar height)
: ConvexInternalShape(new btCapsuleShape(radius, height))
{
}

btScalar CapsuleShape::HalfHeight::get()
{
	return UnmanagedPointer->getHalfHeight();
}

btScalar CapsuleShape::Radius::get()
{
	return UnmanagedPointer->getRadius();
}

int CapsuleShape::UpAxis::get()
{
	return UnmanagedPointer->getUpAxis();
}

btCapsuleShape* CapsuleShape::UnmanagedPointer::get()
{
	return (btCapsuleShape*)ConvexInternalShape::UnmanagedPointer;
}

CapsuleShapeX::CapsuleShapeX(btScalar radius, btScalar height)
: CapsuleShape(new btCapsuleShapeX(radius, height))
{
}

CapsuleShapeZ::CapsuleShapeZ(btScalar radius, btScalar height)
: CapsuleShape(new btCapsuleShapeX(radius, height))
{
}
<commit_msg>- Fix issue 9.<commit_after>#include "StdAfx.h"

#include "CapsuleShape.h"

CapsuleShape::CapsuleShape(btCapsuleShape* shape)
: ConvexInternalShape(shape)
{
}

CapsuleShape::CapsuleShape(btScalar radius, btScalar height)
: ConvexInternalShape(new btCapsuleShape(radius, height))
{
}

btScalar CapsuleShape::HalfHeight::get()
{
	return UnmanagedPointer->getHalfHeight();
}

btScalar CapsuleShape::Radius::get()
{
	return UnmanagedPointer->getRadius();
}

int CapsuleShape::UpAxis::get()
{
	return UnmanagedPointer->getUpAxis();
}

btCapsuleShape* CapsuleShape::UnmanagedPointer::get()
{
	return (btCapsuleShape*)ConvexInternalShape::UnmanagedPointer;
}

CapsuleShapeX::CapsuleShapeX(btScalar radius, btScalar height)
: CapsuleShape(new btCapsuleShapeX(radius, height))
{
}

CapsuleShapeZ::CapsuleShapeZ(btScalar radius, btScalar height)
: CapsuleShape(new btCapsuleShapeZ(radius, height))
{
}
<|endoftext|>


<commit_before>#include <cassert>
#include "CodeGen_Bash.h"

using namespace Bish;

void CodeGen_Bash::indent() {
    for (unsigned i = 0; i < indent_level; i++) {
        stream << "    ";
    }
}

void CodeGen_Bash::visit(const Module *n) {
    for (std::vector<Function *>::const_iterator I = n->functions.begin(),
             E = n->functions.end(); I != E; ++I) {
        (*I)->accept(this);
    }
    // Insert a call to bish_main().
    assert(n->main);
    FunctionCall *call_main = new FunctionCall(n->main->name);
    visit(call_main);
    stream << ";\n";
    delete call_main;
}

void CodeGen_Bash::visit(const Block *n) {
    if (should_print_block_braces()) stream << "{\n";
    indent_level++;
    for (std::vector<IRNode *>::const_iterator I = n->nodes.begin(), E = n->nodes.end();
         I != E; ++I) {
        indent();
        (*I)->accept(this);
        stream << ";\n";
    }
    indent_level--;
    if (should_print_block_braces()) stream << "}\n\n";
}

void CodeGen_Bash::visit(const Variable *n) {
    if (should_quote_variable()) stream << "\"";
    stream << "$" << lookup_name(n);
    if (should_quote_variable()) stream << "\"";
}

void CodeGen_Bash::visit(const ReturnStatement *n) {
    stream << "echo ";
    enable_functioncall_wrap();
    n->value->accept(this);
    disable_functioncall_wrap();
    stream << "; exit";
}

void CodeGen_Bash::visit(const IfStatement *n) {
    stream << "if [[ ";
    enable_functioncall_wrap();
    n->pblock->condition->accept(this);
    disable_functioncall_wrap();
    stream << " ]]; then\n";
    disable_block_braces();
    n->pblock->body->accept(this);

    for (std::vector<PredicatedBlock *>::const_iterator I = n->elses.begin(),
             E = n->elses.end(); I != E; ++I) {
        indent();
        stream << "elif [[ ";
        enable_functioncall_wrap();
        (*I)->condition->accept(this);
        disable_functioncall_wrap();
        stream << " ]]; then\n";
        (*I)->body->accept(this);
    }
    if (n->elseblock) {
        indent();
        stream << "else\n";
        n->elseblock->accept(this);
    }

    enable_block_braces();
    indent();
    stream << "fi";
}

void CodeGen_Bash::visit(const ForLoop *n) {
    stream << "for " << lookup_name(n->variable) << " in ";
    if (n->upper) {
        stream << "$(seq ";
        n->lower->accept(this);
        stream << " ";
        n->upper->accept(this);
        stream << ")";
    } else {
        n->lower->accept(this);
    }
    stream << "; do\n";
    disable_block_braces();
    n->body->accept(this);
    enable_block_braces();
    indent();
    stream << "done";
}

void CodeGen_Bash::visit(const Function *n) {
    stream << "function bish_" << n->name << " ";
    stream << "() ";
    LetScope *s = new LetScope();
    push_let_scope(s);
    // Bash doesn't allow named arguments to functions.
    // We have to translate to positional arguments.
    unsigned i = 1;
    for (std::vector<Variable *>::const_iterator I = n->args.begin(), E = n->args.end(); I != E; ++I, ++i) {
      s->add(*I, convert_string(i));
    }
    n->body->accept(this);
    pop_let_scope();
}

void CodeGen_Bash::visit(const FunctionCall *n) {
    const int nargs = n->args.size();
    if (should_functioncall_wrap()) stream << "$(";
    stream << "bish_" << n->name;
    for (int i = 0; i < nargs; i++) {
        stream << " ";
        bool old = enable_functioncall_wrap();
        if (const FunctionCall *FC = dynamic_cast<const FunctionCall*>(n->args[i])) {
          if (should_quote_variable()) stream << "\"";
          n->args[i]->accept(this);
          if (should_quote_variable()) stream << "\"";
        } else {
          n->args[i]->accept(this);
        }
        set_functioncall_wrap(old);
    }
    if (should_functioncall_wrap()) stream << ")";
}

void CodeGen_Bash::visit(const ExternCall *n) {
    if (should_functioncall_wrap()) stream << "$(";
    for (InterpolatedString::const_iterator I = n->body->begin(), E = n->body->end();
         I != E; ++I) {
        if ((*I).is_str()) {
            stream << (*I).str();
        } else {
            assert((*I).is_var());
            visit((*I).var());
        }
    }
    if (should_functioncall_wrap()) stream << ")";
}

void CodeGen_Bash::visit(const Assignment *n) {
    stream << lookup_name(n->variable) << "=";
    enable_functioncall_wrap();
    n->value->accept(this);
    disable_functioncall_wrap();
}

void CodeGen_Bash::visit(const BinOp *n) {
    bool comparison = false;
    switch (n->op) {
    case BinOp::Eq:
    case BinOp::NotEq:
    case BinOp::LT:
    case BinOp::LTE:
    case BinOp::GT:
    case BinOp::GTE:
        comparison = true;
        break;
    case BinOp::Add:
    case BinOp::Sub:
    case BinOp::Mul:
    case BinOp::Div:
        comparison = false;
        break;
    }

    if (!comparison) stream << "$((";
    disable_quote_variable();
    n->a->accept(this);
    switch (n->op) {
    case BinOp::Eq:
        stream << " -eq ";
        break;
    case BinOp::NotEq:
        stream << " -ne ";
        break;
    case BinOp::LT:
        stream << " -lt ";
        break;
    case BinOp::LTE:
        stream << " -lte ";
        break;
    case BinOp::GT:
        stream << " -gt ";
        break;
    case BinOp::GTE:
        stream << " -gte ";
        break;
    case BinOp::Add:
        stream << " + ";
        break;
    case BinOp::Sub:
        stream << " - ";
        break;
    case BinOp::Mul:
        stream << " * ";
        break;
    case BinOp::Div:
        stream << " / ";
        break;
    }
    n->b->accept(this);
    if (!comparison) stream << "))";
    enable_quote_variable();
}

void CodeGen_Bash::visit(const UnaryOp *n) {
    switch (n->op) {
    case UnaryOp::Negate:
        stream << "-";
        break;
    }
    n->a->accept(this);
}

void CodeGen_Bash::visit(const Integer *n) {
    stream << n->value;
}

void CodeGen_Bash::visit(const Fractional *n) {
    stream << n->value;
}

void CodeGen_Bash::visit(const String *n) {
    stream << "\"" << n->value << "\"";
}

void CodeGen_Bash::visit(const Boolean *n) {
    stream << n->value;
}
<commit_msg>Disable variable quoting in a few places.<commit_after>#include <cassert>
#include "CodeGen_Bash.h"

using namespace Bish;

void CodeGen_Bash::indent() {
    for (unsigned i = 0; i < indent_level; i++) {
        stream << "    ";
    }
}

void CodeGen_Bash::visit(const Module *n) {
    for (std::vector<Function *>::const_iterator I = n->functions.begin(),
             E = n->functions.end(); I != E; ++I) {
        (*I)->accept(this);
    }
    // Insert a call to bish_main().
    assert(n->main);
    FunctionCall *call_main = new FunctionCall(n->main->name);
    visit(call_main);
    stream << ";\n";
    delete call_main;
}

void CodeGen_Bash::visit(const Block *n) {
    if (should_print_block_braces()) stream << "{\n";
    indent_level++;
    for (std::vector<IRNode *>::const_iterator I = n->nodes.begin(), E = n->nodes.end();
         I != E; ++I) {
        indent();
        (*I)->accept(this);
        stream << ";\n";
    }
    indent_level--;
    if (should_print_block_braces()) stream << "}\n\n";
}

void CodeGen_Bash::visit(const Variable *n) {
    if (should_quote_variable()) stream << "\"";
    stream << "$" << lookup_name(n);
    if (should_quote_variable()) stream << "\"";
}

void CodeGen_Bash::visit(const ReturnStatement *n) {
    stream << "echo ";
    enable_functioncall_wrap();
    n->value->accept(this);
    disable_functioncall_wrap();
    stream << "; exit";
}

void CodeGen_Bash::visit(const IfStatement *n) {
    stream << "if [[ ";
    enable_functioncall_wrap();
    n->pblock->condition->accept(this);
    disable_functioncall_wrap();
    stream << " ]]; then\n";
    disable_block_braces();
    n->pblock->body->accept(this);

    for (std::vector<PredicatedBlock *>::const_iterator I = n->elses.begin(),
             E = n->elses.end(); I != E; ++I) {
        indent();
        stream << "elif [[ ";
        enable_functioncall_wrap();
        (*I)->condition->accept(this);
        disable_functioncall_wrap();
        stream << " ]]; then\n";
        (*I)->body->accept(this);
    }
    if (n->elseblock) {
        indent();
        stream << "else\n";
        n->elseblock->accept(this);
    }

    enable_block_braces();
    indent();
    stream << "fi";
}

void CodeGen_Bash::visit(const ForLoop *n) {
    stream << "for " << lookup_name(n->variable) << " in ";
    if (n->upper) {
        stream << "$(seq ";
        n->lower->accept(this);
        stream << " ";
        n->upper->accept(this);
        stream << ")";
    } else {
        disable_quote_variable();
        n->lower->accept(this);
        enable_quote_variable();
    }
    stream << "; do\n";
    disable_block_braces();
    n->body->accept(this);
    enable_block_braces();
    indent();
    stream << "done";
}

void CodeGen_Bash::visit(const Function *n) {
    stream << "function bish_" << n->name << " ";
    stream << "() ";
    LetScope *s = new LetScope();
    push_let_scope(s);
    // Bash doesn't allow named arguments to functions.
    // We have to translate to positional arguments.
    unsigned i = 1;
    for (std::vector<Variable *>::const_iterator I = n->args.begin(), E = n->args.end(); I != E; ++I, ++i) {
      s->add(*I, convert_string(i));
    }
    n->body->accept(this);
    pop_let_scope();
}

void CodeGen_Bash::visit(const FunctionCall *n) {
    const int nargs = n->args.size();
    if (should_functioncall_wrap()) stream << "$(";
    stream << "bish_" << n->name;
    for (int i = 0; i < nargs; i++) {
        stream << " ";
        bool old = enable_functioncall_wrap();
        if (const FunctionCall *FC = dynamic_cast<const FunctionCall*>(n->args[i])) {
          if (should_quote_variable()) stream << "\"";
          n->args[i]->accept(this);
          if (should_quote_variable()) stream << "\"";
        } else {
          n->args[i]->accept(this);
        }
        set_functioncall_wrap(old);
    }
    if (should_functioncall_wrap()) stream << ")";
}

void CodeGen_Bash::visit(const ExternCall *n) {
    if (should_functioncall_wrap()) stream << "$(";
    disable_quote_variable();
    for (InterpolatedString::const_iterator I = n->body->begin(), E = n->body->end();
         I != E; ++I) {
        if ((*I).is_str()) {
            stream << (*I).str();
        } else {
            assert((*I).is_var());
            visit((*I).var());
        }
    }
    enable_quote_variable();
    if (should_functioncall_wrap()) stream << ")";
}

void CodeGen_Bash::visit(const Assignment *n) {
    stream << lookup_name(n->variable) << "=";
    enable_functioncall_wrap();
    n->value->accept(this);
    disable_functioncall_wrap();
}

void CodeGen_Bash::visit(const BinOp *n) {
    bool comparison = false;
    switch (n->op) {
    case BinOp::Eq:
    case BinOp::NotEq:
    case BinOp::LT:
    case BinOp::LTE:
    case BinOp::GT:
    case BinOp::GTE:
        comparison = true;
        break;
    case BinOp::Add:
    case BinOp::Sub:
    case BinOp::Mul:
    case BinOp::Div:
        comparison = false;
        break;
    }

    if (!comparison) stream << "$((";
    disable_quote_variable();
    n->a->accept(this);
    switch (n->op) {
    case BinOp::Eq:
        stream << " -eq ";
        break;
    case BinOp::NotEq:
        stream << " -ne ";
        break;
    case BinOp::LT:
        stream << " -lt ";
        break;
    case BinOp::LTE:
        stream << " -lte ";
        break;
    case BinOp::GT:
        stream << " -gt ";
        break;
    case BinOp::GTE:
        stream << " -gte ";
        break;
    case BinOp::Add:
        stream << " + ";
        break;
    case BinOp::Sub:
        stream << " - ";
        break;
    case BinOp::Mul:
        stream << " * ";
        break;
    case BinOp::Div:
        stream << " / ";
        break;
    }
    n->b->accept(this);
    if (!comparison) stream << "))";
    enable_quote_variable();
}

void CodeGen_Bash::visit(const UnaryOp *n) {
    switch (n->op) {
    case UnaryOp::Negate:
        stream << "-";
        break;
    }
    n->a->accept(this);
}

void CodeGen_Bash::visit(const Integer *n) {
    stream << n->value;
}

void CodeGen_Bash::visit(const Fractional *n) {
    stream << n->value;
}

void CodeGen_Bash::visit(const String *n) {
    stream << "\"" << n->value << "\"";
}

void CodeGen_Bash::visit(const Boolean *n) {
    stream << n->value;
}
<|endoftext|>


<commit_before>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "ColumnPrinter.hh"
#include <typeinfo>
#include <stdexcept>

namespace orc {

  class LongColumnPrinter: public ColumnPrinter {
  private:
    const long* data;
  public:
    LongColumnPrinter(const ColumnVectorBatch& batch);
    ~LongColumnPrinter() {}
    void printRow(unsigned long rowId)  ;
    void reset(const ColumnVectorBatch& batch)  ;
  };

  class DoubleColumnPrinter: public ColumnPrinter {
  private:
    const double* data;
  public:
    DoubleColumnPrinter(const ColumnVectorBatch& batch);
    virtual ~DoubleColumnPrinter() {}
    void printRow(unsigned long rowId)  ;
    void reset(const ColumnVectorBatch& batch)  ;
  };

  class StringColumnPrinter: public ColumnPrinter {
  private:
    const char* const * start;
    const long* length;
  public:
    StringColumnPrinter(const ColumnVectorBatch& batch);
    virtual ~StringColumnPrinter() {}
    void printRow(unsigned long rowId)  ;
    void reset(const ColumnVectorBatch& batch)  ;
  };

  ColumnPrinter::~ColumnPrinter() {
    // PASS
  }

  LongColumnPrinter::LongColumnPrinter(const  ColumnVectorBatch& batch) {
    reset(batch);
  }

  void LongColumnPrinter::reset(const  ColumnVectorBatch& batch) {
    data = dynamic_cast<const LongVectorBatch&>(batch).data.data();
  }

  void LongColumnPrinter::printRow(unsigned long rowId) {
    std::cout << data[rowId];
  }

  DoubleColumnPrinter::DoubleColumnPrinter(const  ColumnVectorBatch& batch) {
    reset(batch);
  }

  void DoubleColumnPrinter::reset(const  ColumnVectorBatch& batch) {
    data = dynamic_cast<const DoubleVectorBatch&>(batch).data.data();
  }

  void DoubleColumnPrinter::printRow(unsigned long rowId) {
    std::cout << data[rowId];
  }

  StringColumnPrinter::StringColumnPrinter(const ColumnVectorBatch& batch) {
    reset(batch);
  }

  void StringColumnPrinter::reset(const ColumnVectorBatch& batch) {
    start = dynamic_cast<const StringVectorBatch&>(batch).data.data();
    length = dynamic_cast<const StringVectorBatch&>(batch).length.data();
  }

  void StringColumnPrinter::printRow(unsigned long rowId) {
    std::cout.write(start[rowId], length[rowId]);
  }

  StructColumnPrinter::StructColumnPrinter(const ColumnVectorBatch& batch) {
    const StructVectorBatch& structBatch =
      dynamic_cast<const StructVectorBatch&>(batch);
    for(std::vector<ColumnVectorBatch*>::const_iterator ptr=structBatch.fields.begin();
        ptr != structBatch.fields.end(); ++ptr) {
      if (typeid(**ptr) == typeid(LongVectorBatch)) {
        fields.push_back(new LongColumnPrinter(**ptr));
      } else if (typeid(**ptr) == typeid(DoubleVectorBatch)) {
        fields.push_back(new DoubleColumnPrinter(**ptr));
      } else if (typeid(**ptr) == typeid(StringVectorBatch)) {
        fields.push_back(new StringColumnPrinter(**ptr));
      } else if (typeid(**ptr) == typeid(StructVectorBatch)) {
        fields.push_back(new StructColumnPrinter(**ptr));
      } else {
        throw std::logic_error("unknown batch type");
      }
    }
  }

  StructColumnPrinter::~StructColumnPrinter() {
    for (size_t i = 0; i < fields.size(); i++) {
      delete fields[i];
    }
  }

  void StructColumnPrinter::reset(const ColumnVectorBatch& batch) {
    const StructVectorBatch& structBatch =
      dynamic_cast<const StructVectorBatch&>(batch);
    for(size_t i=0; i < fields.size(); ++i) {
      fields[i]->reset(*(structBatch.fields[i]));
    }
  }

  void StructColumnPrinter::printRow(unsigned long rowId) {
    if (fields.size() > 0) {
      for (std::vector<ColumnPrinter*>::iterator ptr = fields.begin(); ptr != fields.end(); ++ptr) {
        (*ptr)->printRow(rowId);
        std::cout << "\t";
      }
      std::cout << "\n";
    }
  }
}
<commit_msg>Fixed #52.<commit_after>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "ColumnPrinter.hh"
#include <typeinfo>
#include <stdexcept>

namespace orc {

  class LongColumnPrinter: public ColumnPrinter {
  private:
    const long* data;
  public:
    LongColumnPrinter(const ColumnVectorBatch& batch);
    ~LongColumnPrinter() {}
    void printRow(unsigned long rowId)  ;
    void reset(const ColumnVectorBatch& batch)  ;
  };

  class DoubleColumnPrinter: public ColumnPrinter {
  private:
    const double* data;
  public:
    DoubleColumnPrinter(const ColumnVectorBatch& batch);
    virtual ~DoubleColumnPrinter() {}
    void printRow(unsigned long rowId)  ;
    void reset(const ColumnVectorBatch& batch)  ;
  };

  class StringColumnPrinter: public ColumnPrinter {
  private:
    const char* const * start;
    const long* length;
  public:
    StringColumnPrinter(const ColumnVectorBatch& batch);
    virtual ~StringColumnPrinter() {}
    void printRow(unsigned long rowId)  ;
    void reset(const ColumnVectorBatch& batch)  ;
  };

  ColumnPrinter::~ColumnPrinter() {
    // PASS
  }

  LongColumnPrinter::LongColumnPrinter(const  ColumnVectorBatch& batch) {
    reset(batch);
  }

  void LongColumnPrinter::reset(const  ColumnVectorBatch& batch) {
    data = dynamic_cast<const LongVectorBatch&>(batch).data.data();
  }

  void LongColumnPrinter::printRow(unsigned long rowId) {
    std::cout << data[rowId];
  }

  DoubleColumnPrinter::DoubleColumnPrinter(const  ColumnVectorBatch& batch) {
    reset(batch);
  }

  void DoubleColumnPrinter::reset(const  ColumnVectorBatch& batch) {
    data = dynamic_cast<const DoubleVectorBatch&>(batch).data.data();
  }

  void DoubleColumnPrinter::printRow(unsigned long rowId) {
    std::cout << data[rowId];
  }

  StringColumnPrinter::StringColumnPrinter(const ColumnVectorBatch& batch) {
    reset(batch);
  }

  void StringColumnPrinter::reset(const ColumnVectorBatch& batch) {
    start = dynamic_cast<const StringVectorBatch&>(batch).data.data();
    length = dynamic_cast<const StringVectorBatch&>(batch).length.data();
  }

  void StringColumnPrinter::printRow(unsigned long rowId) {
    std::cout.write(start[rowId], length[rowId]);
  }

  StructColumnPrinter::StructColumnPrinter(const ColumnVectorBatch& batch) {
    const StructVectorBatch& structBatch =
      dynamic_cast<const StructVectorBatch&>(batch);
    for(std::vector<ColumnVectorBatch*>::const_iterator ptr=structBatch.fields.begin();
        ptr != structBatch.fields.end(); ++ptr) {
      if (typeid(**ptr) == typeid(LongVectorBatch)) {
        fields.push_back(new LongColumnPrinter(**ptr));
      } else if (typeid(**ptr) == typeid(DoubleVectorBatch)) {
        fields.push_back(new DoubleColumnPrinter(**ptr));
      } else if (typeid(**ptr) == typeid(StringVectorBatch)) {
        fields.push_back(new StringColumnPrinter(**ptr));
      } else if (typeid(**ptr) == typeid(StructVectorBatch)) {
        fields.push_back(new StructColumnPrinter(**ptr));
      } else {
        throw std::logic_error("unknown batch type");
      }
    }
  }

  StructColumnPrinter::~StructColumnPrinter() {
    for (size_t i = 0; i < fields.size(); i++) {
      delete fields[i];
    }
  }

  void StructColumnPrinter::reset(const ColumnVectorBatch& batch) {
    const StructVectorBatch& structBatch =
      dynamic_cast<const StructVectorBatch&>(batch);
    for(size_t i=0; i < fields.size(); ++i) {
      fields[i]->reset(*(structBatch.fields[i]));
    }
  }

  void StructColumnPrinter::printRow(unsigned long rowId) {
    if (fields.size() > 0) {
      for (std::vector<ColumnPrinter*>::iterator ptr = fields.begin(); ptr != fields.end(); ++ptr) {
        (*ptr)->printRow(rowId);

        std::cout << "\t";
      }
      std::cout << "\n";
    }
  }
}
<|endoftext|>