<commit_before>#ifndef __PROBABILITY_DISTRIBUTIONS__HMM_IMPL_HPP__
#define __PROBABILITY_DISTRIBUTIONS__HMM_IMPL_HPP__

#include "hmm.hpp"

#include "mixture.hpp"

namespace ProbabilityDistributions {
  template <unsigned int SS, class D, class W, class T, class... Dists>
  HMM<SS,D,W,T,Dists...>::HMM(Dists&&... dists):
    have_asymmetric_(CompileUtils::or_<
        std::is_base_of<
          AsymmetricDistribution<typename CompileUtils::clean_type<Dists>::type,D,W,T>,
          typename CompileUtils::clean_type<Dists>::type>::value...>::value),
    stop_condition_(1e-4),
    max_iterations_(1000),
    components_(tuple_type(dists...)) {
      create_component_pointers(
          typename CompileUtils::tuple_sequence_generator<tuple_type>::type());
    }

  template <unsigned int SS, class D, class W, class T, class... Dists>
  template <size_t... S>
  void HMM<SS,D,W,T,Dists...>::create_component_pointers(
      CompileUtils::sequence<S...>) {
    components_pointers_ =
      std::vector<Distribution<D,W,T>*>({&std::get<S>(components_)...});
  }

  template <unsigned int SS, class D, class W, class T, class... Dists>
  template <class RNG>
  void HMM<SS,D,W,T,Dists...>::sample(MA::Array<D>& samples,
      size_t n_samples, RNG& rng) const {
    MA::Size::SizeType size(2);
    size[0] = n_samples;
    size[1] = SS;
    samples.resize(size);

    MA::Array<D> components_samples;
    MA::Array<unsigned int> components_indexes;
    std::vector<unsigned int> indexes(n_samples);

    initial_weights_.sample(components_samples, 1, rng);
    initial_weights_.sample_to_index(components_indexes, components_samples);
    indexes[0] = components_indexes(0);

    for (size_t i = 1; i < n_samples; i++) {
      unsigned int k = indexes[i-1];
      transition_weights_[k].sample(components_samples, 1, rng);
      transition_weights_[k].sample_to_index(components_indexes,
          components_samples);
      indexes[i] = components_indexes(0);
    }

    MA::Slice<D> slice(samples, 0);
    for (size_t i = 0; i < n_samples; i++) {
      MA::Array<D> sample = slice.get_element(i);
      sample_components(sample, indexes[i], rng,
          typename CompileUtils::tuple_sequence_generator<tuple_type>::type());
    }
  }

  template <unsigned int SS, class D, class W, class T, class... Dists>
  template <class RNG, size_t... S>
  void HMM<SS,D,W,T,Dists...>::sample_components(MA::Array<D>& sample,
      size_t component_id, RNG& rng, CompileUtils::sequence<S...>) const {
    bool vec[] = {sample_component<S>(sample, component_id, rng)...};
    (void)vec;
  }

  template <unsigned int SS, class D, class W, class T, class... Dists>
  template <size_t I, class RNG>
  bool HMM<SS,D,W,T,Dists...>::sample_component(MA::Array<D>& sample,
      size_t component_id, RNG& rng) const {
    if (I != component_id)
      return false;
    std::get<I>(components_).sample(sample, 1, rng);
    return true;
  }

  template <unsigned int SS, class D, class W, class T, class... Dists>
  T HMM<SS,D,W,T,Dists...>::log_likelihood(MA::ConstArray<D> const& data,
      MA::ConstArray<W> const& weight) const {
    check_data_and_weight(data, weight);

    MA::Array<LogNumber> prob_emissions;
    build_prob_emissons(prob_emissions, data);

    MA::Array<LogNumber> alpha, beta;
    build_alpha_beta(alpha, beta, prob_emissions, weight, data);

    LogNumber ll = 0;
    size_t n_samples = data.size()[0];
    for (unsigned int i = 0; i < K; i++)
      ll += alpha(i, n_samples-1);

    return ll.get_val();
  }

  template <unsigned int SS, class D, class W, class T, class... Dists>
  void HMM<SS,D,W,T,Dists...>::build_expectation(
      MA::Array<W>& expected_weight, MA::ConstArray<W> const& weight,
      MA::ConstArray<T> const& gamma) const {
    expected_weight.resize({K, weight.size()[0]});

    for (unsigned int t = 0; t < weight.size()[0]; t++)
      for (unsigned int i = 0; i < K; i++)
        expected_weight(i,t) = gamma(i,t) * weight(t);
  }

  template <unsigned int SS, class D, class W, class T, class... Dists>
  void HMM<SS,D,W,T,Dists...>::build_prob_emissons(
      MA::Array<LogNumber>& prob_emissions,
      MA::ConstArray<D> const& data) const {
    unsigned int n_samples = data.size()[0];
    prob_emissions.resize({K, n_samples});

    MA::Array<W> null_weight({1});
    null_weight(0) = 1;
    MA::Size sample_size({1, SS});

    MA::ConstSlice<D> data_slice(data, 0);

    for (unsigned int t = 0; t < data_slice.total_left_size(); t++) {
      MA::ConstArray<D> sample = data_slice.get_element(t);
      sample.resize(sample_size);
      for (unsigned int i = 0; i < K; i++)
        prob_emissions(i,t).from_log(
          components_pointers_[i]->log_likelihood(sample, null_weight));
    }
  }

  template <unsigned int SS, class D, class W, class T, class... Dists>
  void HMM<SS,D,W,T,Dists...>::build_alpha_beta(
      MA::Array<LogNumber>& alpha, MA::Array<LogNumber>& beta,
      MA::ConstArray<LogNumber> const& prob_emissions,
      MA::ConstArray<W> const& weight,
      MA::ConstArray<D> const& data) const {
    unsigned int n_samples = data.size()[0];

    alpha.resize({K, n_samples});
    beta.resize({K, n_samples});

    for (unsigned int i = 0; i < K; i++) {
      alpha(i,0) = initial_weights_.get_p()[i] *
        ((1-weight(0)) + weight(0) * prob_emissions(i,0));
      beta(i,n_samples-1) = 1;
    }

    for (unsigned int t = 1; t < n_samples; t++) {
      for (unsigned int i = 0; i < K; i++) {
        alpha(i,t) = 0;
        for (unsigned int j = 0; j < K; j++)
          alpha(i,t) += alpha(j,t-1) * transition_weights_[j].get_p()[i];
        alpha(i,t) *= get_adjusted_weight(i, t, weight, prob_emissions);
      }
    }

    for (unsigned int t = n_samples-1; t > 0; t--) {
      for (unsigned int i = 0; i < K; i++) {
        beta(i,t-1) = 0;
        for (unsigned int j = 0; j < K; j++)
          beta(i,t-1) += beta(j,t) * transition_weights_[i].get_p()[j] *
            get_adjusted_weight(j, t, weight, prob_emissions);
      }
    }
  }

  template <unsigned int SS, class D, class W, class T, class... Dists>
  void HMM<SS,D,W,T,Dists...>::build_gamma(
      MA::Array<W>& gamma,
      MA::ConstArray<LogNumber> const& alpha,
      MA::ConstArray<LogNumber> const& beta) const {
    gamma.resize(alpha.size());
    for (unsigned int t = 0; t < alpha.size()[1]; t++) {
      LogNumber sum = 0;
      std::vector<LogNumber> vals(alpha.size()[0]);
      for (unsigned int i = 0; i < alpha.size()[0]; i++) {
        vals[i] = alpha(i,t) * beta(i,t);
        sum += vals[i];
      }
      for (unsigned int i = 0; i < alpha.size()[0]; i++)
        gamma(i,t) = (vals[i] / sum).to_double();
    }
  }

  template <unsigned int SS, class D, class W, class T, class... Dists>
  void HMM<SS,D,W,T,Dists...>::build_xi(
      MA::Array<W>& xi,
      MA::ConstArray<LogNumber> const& alpha,
      MA::ConstArray<LogNumber> const& beta,
      MA::ConstArray<LogNumber> const& prob_emissions,
      MA::ConstArray<W> const& weight) const {
    xi.resize({K, K, alpha.size()[1]-1});
    for (unsigned int t = 0; t < alpha.size()[1]-1; t++) {
      LogNumber sum = 0;
      for (unsigned int i = 0; i < K; i++)
        sum += alpha(i,t) * beta(i,t);

      for (unsigned int i = 0; i < K; i++)
        for (unsigned int j = 0; j < K; j++)
          xi(i,j,t) = (alpha(i,t) * beta(j,t+1) *
            transition_weights_[i].get_p()[j] *
            get_adjusted_weight(j, t+1, weight, prob_emissions) / sum).to_double();
    }
  }

  template <unsigned int SS, class D, class W, class T, class... Dists>
  LogNumber HMM<SS,D,W,T,Dists...>::get_adjusted_weight(
      unsigned int component, unsigned int sample,
      MA::ConstArray<W> const& weight,
      MA::ConstArray<LogNumber> const& prob_emissions) const {
    return (1-weight(sample)) +
      weight(sample) * prob_emissions(component, sample);
  }

  template <unsigned int SS, class D, class W, class T, class... Dists>
  template <size_t... S>
  void HMM<SS,D,W,T,Dists...>::MLE_as_mixture(MA::ConstArray<D> const& data,
      MA::ConstArray<W> const& weight, std::vector<size_t> const& indexes,
      CompileUtils::sequence<S...>) {
    auto mix = make_mixture(std::get<S>(components_)...);
    auto t1 = std::make_tuple(
        mix.template get_component<S>() = std::get<S>(components_)...);
    (void)t1;
    mix.MLE(data, weight, indexes);
    auto t2 = std::make_tuple(
        std::get<S>(components_) = mix.template get_component<S>()...);
    (void)t2;

    initial_weights_ = mix.get_mixture_weights();
    for (unsigned int i = 0; i < K; i++)
      transition_weights_[i] = initial_weights_;
  }

  template <unsigned int SS, class D, class W, class T, class... Dists>
  void HMM<SS,D,W,T,Dists...>::MLE(MA::ConstArray<D> const& data,
      MA::ConstArray<W> const& weight, std::vector<size_t> const& indexes) {
//    printf("---------------\nstarting MLE\n---------------\n");
    check_data_and_weight(data, weight);

    size_t n_samples = data.size()[0];

    std::vector<size_t> const* index_pointer = &indexes;

    for (unsigned int i = 0; i < K; i++)
      if (components_pointers_[i]->require_sorted() && indexes.size() == 0) {
        index_pointer = new
          std::vector<size_t>(Distribution<D,W,T>::sort_data(data));
        break;
      }

    MLE_as_mixture(data, weight, *index_pointer,
      typename CompileUtils::tuple_sequence_generator<tuple_type>::type());

    MA::Array<W> expected_weight;

    bool fixed_asymmetries = false;
    if (have_asymmetric_) {
      fixed_asymmetries = true;
      fix_all_asymmetries(
          typename CompileUtils::tuple_sequence_generator<tuple_type>::type());
    }

    while (1) {
      T ll_old = -INFINITY, ll_new = -INFINITY;
      size_t it = 0;

      do {
        MA::Array<LogNumber> prob_emissions;
        build_prob_emissons(prob_emissions, data);

        MA::Array<LogNumber> alpha, beta;
        build_alpha_beta(alpha, beta, prob_emissions, weight, data);

        MA::Array<W> gamma;
        build_gamma(gamma, alpha, beta);

        MA::Array<W> xi;
        build_xi(xi, alpha, beta, prob_emissions, weight);

        build_expectation(expected_weight, weight, gamma);

        ll_old = ll_new;

        MA::Slice<W> weight_slice(expected_weight, 0);

        std::vector<T> initial_weights(K);

        for (unsigned int i = 0; i < K; i++) {
          components_pointers_[i]->MLE(data, weight_slice.get_element(i),
              *index_pointer);

          initial_weights[i] = gamma(i, 0);

          T den = 0;
          std::vector<T> num(K, 0);
          for (unsigned int t = 0; t < n_samples-1; t++) {
            den += gamma(i, t);
            for (unsigned int j = 0; j < K; j++)
              num[j] += xi(i, j, t);
          }

          std::vector<T> transition_weights(K);
          for (unsigned int j = 0; j < K; j++)
            transition_weights[j] = num[j]/den;
          transition_weights_[i].set_p(transition_weights);
        }

        initial_weights_.set_p(initial_weights);

        ll_new = log_likelihood(data, weight);
        //assert(ll_new >= ll_old);
        assert(ll_new >= ll_old - 1e-8);

        it++;
      } while(ll_new - ll_old > stop_condition_ && it < max_iterations_);

      if (!fixed_asymmetries)
        break;

      fixed_asymmetries = false;
      free_all_asymmetries(
          typename CompileUtils::tuple_sequence_generator<tuple_type>::type());
    }

    if (index_pointer != &indexes)
      delete index_pointer;
  }

  template <unsigned int SS, class D, class W, class T, class... Dists>
  void HMM<SS,D,W,T,Dists...>::check_data_and_weight(
      MA::ConstArray<D> const& data, MA::ConstArray<W> const& weight) const {
    assert(data.size().size() == 2);
    assert(data.size()[0] > 0);
    assert(data.size()[1] == SS);
    assert(weight.size().size() == 1);
    assert(weight.size()[0] == data.size()[0]);
  }
};

#endif
<commit_msg>Fixed somethings in hmm implementation.<commit_after>#ifndef __PROBABILITY_DISTRIBUTIONS__HMM_IMPL_HPP__
#define __PROBABILITY_DISTRIBUTIONS__HMM_IMPL_HPP__

#include "hmm.hpp"

#include "mixture.hpp"

namespace ProbabilityDistributions {
  template <unsigned int SS, class D, class W, class T, class... Dists>
  HMM<SS,D,W,T,Dists...>::HMM(Dists&&... dists):
    have_asymmetric_(CompileUtils::or_<
        std::is_base_of<
          AsymmetricDistribution<typename CompileUtils::clean_type<Dists>::type,D,W,T>,
          typename CompileUtils::clean_type<Dists>::type>::value...>::value),
    stop_condition_(1e-4),
    max_iterations_(1000),
    components_(tuple_type(dists...)) {
      create_component_pointers(
          typename CompileUtils::tuple_sequence_generator<tuple_type>::type());
    }

  template <unsigned int SS, class D, class W, class T, class... Dists>
  template <size_t... S>
  void HMM<SS,D,W,T,Dists...>::create_component_pointers(
      CompileUtils::sequence<S...>) {
    components_pointers_ =
      std::vector<Distribution<D,W,T>*>({&std::get<S>(components_)...});
  }

  template <unsigned int SS, class D, class W, class T, class... Dists>
  template <class RNG>
  void HMM<SS,D,W,T,Dists...>::sample(MA::Array<D>& samples,
      size_t n_samples, RNG& rng) const {
    MA::Size::SizeType size(2);
    size[0] = n_samples;
    size[1] = SS;
    samples.resize(size);

    MA::Array<D> components_samples;
    MA::Array<unsigned int> components_indexes;
    std::vector<unsigned int> indexes(n_samples);

    initial_weights_.sample(components_samples, 1, rng);
    initial_weights_.sample_to_index(components_indexes, components_samples);
    indexes[0] = components_indexes(0);

    for (size_t i = 1; i < n_samples; i++) {
      unsigned int k = indexes[i-1];
      transition_weights_[k].sample(components_samples, 1, rng);
      transition_weights_[k].sample_to_index(components_indexes,
          components_samples);
      indexes[i] = components_indexes(0);
    }

    MA::Slice<D> slice(samples, 0);
    for (size_t i = 0; i < n_samples; i++) {
      MA::Array<D> sample = slice.get_element(i);
      sample_components(sample, indexes[i], rng,
          typename CompileUtils::tuple_sequence_generator<tuple_type>::type());
    }
  }

  template <unsigned int SS, class D, class W, class T, class... Dists>
  template <class RNG, size_t... S>
  void HMM<SS,D,W,T,Dists...>::sample_components(MA::Array<D>& sample,
      size_t component_id, RNG& rng, CompileUtils::sequence<S...>) const {
    bool vec[] = {sample_component<S>(sample, component_id, rng)...};
    (void)vec;
  }

  template <unsigned int SS, class D, class W, class T, class... Dists>
  template <size_t I, class RNG>
  bool HMM<SS,D,W,T,Dists...>::sample_component(MA::Array<D>& sample,
      size_t component_id, RNG& rng) const {
    if (I != component_id)
      return false;
    std::get<I>(components_).sample(sample, 1, rng);
    return true;
  }

  template <unsigned int SS, class D, class W, class T, class... Dists>
  T HMM<SS,D,W,T,Dists...>::log_likelihood(MA::ConstArray<D> const& data,
      MA::ConstArray<W> const& weight) const {
    check_data_and_weight(data, weight);

    MA::Array<LogNumber> prob_emissions;
    build_prob_emissons(prob_emissions, data);

    MA::Array<LogNumber> alpha, beta;
    build_alpha_beta(alpha, beta, prob_emissions, weight, data);

    LogNumber ll = 0;
    size_t n_samples = data.size()[0];
    for (unsigned int i = 0; i < K; i++)
      ll += alpha(i, n_samples-1);

    return ll.get_val();
  }

  template <unsigned int SS, class D, class W, class T, class... Dists>
  void HMM<SS,D,W,T,Dists...>::build_expectation(
      MA::Array<W>& expected_weight, MA::ConstArray<W> const& weight,
      MA::ConstArray<T> const& gamma) const {
    expected_weight.resize({K, weight.size()[0]});

    for (unsigned int t = 0; t < weight.size()[0]; t++)
      for (unsigned int i = 0; i < K; i++)
        expected_weight(i,t) = gamma(i,t) * weight(t);
  }

  template <unsigned int SS, class D, class W, class T, class... Dists>
  void HMM<SS,D,W,T,Dists...>::build_prob_emissons(
      MA::Array<LogNumber>& prob_emissions,
      MA::ConstArray<D> const& data) const {
    unsigned int n_samples = data.size()[0];
    prob_emissions.resize({K, n_samples});

    MA::Array<W> null_weight({1});
    null_weight(0) = 1;
    MA::Size sample_size({1, SS});

    MA::ConstSlice<D> data_slice(data, 0);

    for (unsigned int t = 0; t < data_slice.total_left_size(); t++) {
      MA::ConstArray<D> sample = data_slice.get_element(t);
      sample.resize(sample_size);
      for (unsigned int i = 0; i < K; i++)
        prob_emissions(i,t).from_log(
          components_pointers_[i]->log_likelihood(sample, null_weight));
    }
  }

  template <unsigned int SS, class D, class W, class T, class... Dists>
  void HMM<SS,D,W,T,Dists...>::build_alpha_beta(
      MA::Array<LogNumber>& alpha, MA::Array<LogNumber>& beta,
      MA::ConstArray<LogNumber> const& prob_emissions,
      MA::ConstArray<W> const& weight,
      MA::ConstArray<D> const& data) const {
    unsigned int n_samples = data.size()[0];

    alpha.resize({K, n_samples});
    beta.resize({K, n_samples});

    for (unsigned int i = 0; i < K; i++) {
      alpha(i,0) = initial_weights_.get_p()[i] *
        ((1-weight(0)) + weight(0) * prob_emissions(i,0));
      beta(i,n_samples-1) = 1;
    }

    for (unsigned int t = 1; t < n_samples; t++) {
      for (unsigned int i = 0; i < K; i++) {
        alpha(i,t) = 0;
        for (unsigned int j = 0; j < K; j++)
          alpha(i,t) += alpha(j,t-1) * transition_weights_[j].get_p()[i];
        alpha(i,t) *= get_adjusted_weight(i, t, weight, prob_emissions);
      }
    }

    for (unsigned int t = n_samples-1; t > 0; t--) {
      for (unsigned int i = 0; i < K; i++) {
        beta(i,t-1) = 0;
        for (unsigned int j = 0; j < K; j++)
          beta(i,t-1) += beta(j,t) * transition_weights_[i].get_p()[j] *
            get_adjusted_weight(j, t, weight, prob_emissions);
      }
    }
  }

  template <unsigned int SS, class D, class W, class T, class... Dists>
  void HMM<SS,D,W,T,Dists...>::build_gamma(
      MA::Array<W>& gamma,
      MA::ConstArray<LogNumber> const& alpha,
      MA::ConstArray<LogNumber> const& beta) const {
    gamma.resize(alpha.size());
    for (unsigned int t = 0; t < alpha.size()[1]; t++) {
      LogNumber sum = 0;
      std::vector<LogNumber> vals(alpha.size()[0]);
      for (unsigned int i = 0; i < alpha.size()[0]; i++) {
        vals[i] = alpha(i,t) * beta(i,t);
        sum += vals[i];
      }
      for (unsigned int i = 0; i < alpha.size()[0]; i++)
        gamma(i,t) = (vals[i] / sum).to_double();
    }
  }

  template <unsigned int SS, class D, class W, class T, class... Dists>
  void HMM<SS,D,W,T,Dists...>::build_xi(
      MA::Array<W>& xi,
      MA::ConstArray<LogNumber> const& alpha,
      MA::ConstArray<LogNumber> const& beta,
      MA::ConstArray<LogNumber> const& prob_emissions,
      MA::ConstArray<W> const& weight) const {
    xi.resize({K, K, alpha.size()[1]-1});
    for (unsigned int t = 0; t < alpha.size()[1]-1; t++) {
      LogNumber sum = 0;
      for (unsigned int i = 0; i < K; i++)
        sum += alpha(i,t) * beta(i,t);

      for (unsigned int i = 0; i < K; i++)
        for (unsigned int j = 0; j < K; j++)
          xi(i,j,t) = (alpha(i,t) * beta(j,t+1) *
            transition_weights_[i].get_p()[j] *
            get_adjusted_weight(j, t+1, weight, prob_emissions) / sum).to_double();
    }
  }

  template <unsigned int SS, class D, class W, class T, class... Dists>
  LogNumber HMM<SS,D,W,T,Dists...>::get_adjusted_weight(
      unsigned int component, unsigned int sample,
      MA::ConstArray<W> const& weight,
      MA::ConstArray<LogNumber> const& prob_emissions) const {
    return (1-weight(sample)) +
      weight(sample) * prob_emissions(component, sample);
  }

  template <unsigned int SS, class D, class W, class T, class... Dists>
  template <size_t... S>
  void HMM<SS,D,W,T,Dists...>::MLE_as_mixture(MA::ConstArray<D> const& data,
      MA::ConstArray<W> const& weight, std::vector<size_t> const& indexes,
      CompileUtils::sequence<S...>) {
    auto mix = make_mixture(std::get<S>(components_)...);
    mix.set_max_iterations(max_iterations_);
    mix.set_stop_condition(stop_condition_);

    auto t1 = std::make_tuple(
        mix.template get_component<S>() = std::get<S>(components_)...);
    (void)t1;
    mix.MLE(data, weight, indexes);
    auto t2 = std::make_tuple(
        std::get<S>(components_) = mix.template get_component<S>()...);
    (void)t2;

    // In tests have shown that copying the weights can get to lower local
    // minima.
    //initial_weights_ = mix.get_mixture_weights();
    //for (unsigned int i = 0; i < K; i++)
    //  transition_weights_[i] = initial_weights_;
  }

  template <unsigned int SS, class D, class W, class T, class... Dists>
  void HMM<SS,D,W,T,Dists...>::MLE(MA::ConstArray<D> const& data,
      MA::ConstArray<W> const& weight, std::vector<size_t> const& indexes) {
    check_data_and_weight(data, weight);

    size_t n_samples = data.size()[0];

    std::vector<size_t> const* index_pointer = &indexes;

    for (unsigned int i = 0; i < K; i++)
      if (components_pointers_[i]->require_sorted() && indexes.size() == 0) {
        index_pointer = new
          std::vector<size_t>(Distribution<D,W,T>::sort_data(data));
        break;
      }

    MLE_as_mixture(data, weight, *index_pointer,
      typename CompileUtils::tuple_sequence_generator<tuple_type>::type());

    MA::Array<W> expected_weight;

    bool fixed_asymmetries = false;
    if (have_asymmetric_) {
      fixed_asymmetries = true;
      fix_all_asymmetries(
          typename CompileUtils::tuple_sequence_generator<tuple_type>::type());
    }

    while (1) {
      T ll_old = -INFINITY, ll_new = -INFINITY;
      size_t it = 0;

      do {
        MA::Array<LogNumber> prob_emissions;
        build_prob_emissons(prob_emissions, data);

        MA::Array<LogNumber> alpha, beta;
        build_alpha_beta(alpha, beta, prob_emissions, weight, data);

        MA::Array<W> gamma;
        build_gamma(gamma, alpha, beta);

        MA::Array<W> xi;
        build_xi(xi, alpha, beta, prob_emissions, weight);

        build_expectation(expected_weight, weight, gamma);

        ll_old = ll_new;

        MA::Slice<W> weight_slice(expected_weight, 0);

        std::vector<T> initial_weights(K);

        for (unsigned int i = 0; i < K; i++) {
          components_pointers_[i]->MLE(data, weight_slice.get_element(i),
              *index_pointer);

          initial_weights[i] = gamma(i, 0);

          T den = 0;
          std::vector<T> num(K, 0);
          for (unsigned int t = 0; t < n_samples-1; t++) {
            den += gamma(i, t);
            for (unsigned int j = 0; j < K; j++)
              num[j] += xi(i, j, t);
          }

          std::vector<T> transition_weights(K);
          for (unsigned int j = 0; j < K; j++)
            transition_weights[j] = num[j]/den;
          transition_weights_[i].set_p(transition_weights);
        }

        initial_weights_.set_p(initial_weights);

        ll_new = log_likelihood(data, weight);
        //assert(ll_new >= ll_old);
        //assert(ll_new >= ll_old - 1e-8);

        it++;
      } while(std::abs(ll_new - ll_old) > stop_condition_ &&
              it < max_iterations_);

      if (!fixed_asymmetries)
        break;

      fixed_asymmetries = false;
      free_all_asymmetries(
          typename CompileUtils::tuple_sequence_generator<tuple_type>::type());
    }

    if (index_pointer != &indexes)
      delete index_pointer;
  }

  template <unsigned int SS, class D, class W, class T, class... Dists>
  void HMM<SS,D,W,T,Dists...>::check_data_and_weight(
      MA::ConstArray<D> const& data, MA::ConstArray<W> const& weight) const {
    assert(data.size().size() == 2);
    assert(data.size()[0] > 0);
    assert(data.size()[1] == SS);
    assert(weight.size().size() == 1);
    assert(weight.size()[0] == data.size()[0]);
  }
};

#endif
<|endoftext|>


<commit_before>#pragma once

#include <string>
#include <sstream>
#include <vector>
#include <json.hpp>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <mos/sim/ray.hpp>
#include <chrono>

namespace mos {

/**
 * @brief Load text from file.
 * @param path Full path.
 * @return String with all content.
 */
std::string text(const std::string &path);

std::vector<std::string> &split(const std::string &s, char delim,
                                std::vector<std::string> &elems);

std::vector<std::string> split(const std::string &s, char delim);

glm::mat4 jsonarray_to_mat4(const nlohmann::json &array);
glm::vec3 jsonarray_to_vec3(const nlohmann::json &array);
glm::quat jsonarray_to_quat(const nlohmann::json &array);
glm::vec4 jsonarray_to_vec4(const nlohmann::json &array);

glm::vec3 position(const glm::mat4 &mat);

int now_ms();

mos::sim::Ray un_project(const glm::vec2 &position,
                         const glm::mat4 &view,
                         const glm::mat4 &projection,
                         const glm::uvec2 &resolution);

auto hex_color(const int hex) -> glm::vec4;

}
<commit_msg>Depricate util functions.<commit_after>#pragma once

#include <string>
#include <sstream>
#include <vector>
#include <json.hpp>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <mos/sim/ray.hpp>
#include <chrono>

namespace mos {

// Load full string from text file
auto text(const std::string &path) -> std::string;

[[deprecated]]
auto split(const std::string &s, char delim,
      std::vector<std::string> &elems) -> std::vector<std::string> &;
[[deprecated]]
auto split(const std::string &s, char delim) -> std::vector<std::string>;

auto jsonarray_to_mat4(const nlohmann::json &array) -> glm::mat4;
auto jsonarray_to_vec3(const nlohmann::json &array) -> glm::vec3;
auto jsonarray_to_quat(const nlohmann::json &array) -> glm::quat;
auto jsonarray_to_vec4(const nlohmann::json &array) -> glm::vec4;

[[deprecated]]
auto position(const glm::mat4 &mat) -> glm::vec3;

int now_ms();

auto un_project(const glm::vec2 &position,
                         const glm::mat4 &view,
                         const glm::mat4 &projection,
                const glm::uvec2 &resolution) -> mos::sim::Ray;

auto hex_color(const int hex) -> glm::vec4;

}
<|endoftext|>


<commit_before>///////////////////////////////////////////////////////////////////////////////////
// Tryx Plugin System made by Avra Neel Chakraborty                              //
//                                                                               //
// Copyright (c) 2017 Avra Neel Chakraborty                                      //
//                                                                               //
// Permission is hereby granted, free of charge, to any person obtaining a copy  //
// of this software and associated documentation files (the "Software"), to deal //
// in the Software without restriction, including without limitation the rights  //
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell     //
// copies of the Software, and to permit persons to whom the Software is         //
// furnished to do so, subject to the following conditions:                      //
//                                                                               //
// The above copyright notice and this permission notice shall be included in    //
// all copies or substantial portions of the Software.                           //
///////////////////////////////////////////////////////////////////////////////////

#ifndef TRYX_LINKEDLIST_HPP
#define TRYX_LINKEDLIST_HPP

#include <stdexcept>

namespace Tryx {

  template<typename T,typename U>
  class TryxList {
    public:
      TryxList() {
        root = new Node;
      }

      ~TryxList() { deleteList(); }

      void create(T param1,U param2) {
        if(root == nullptr) {
          Node* nn = new Node(param1,param2);
          root = nn;
        }
        else throw std::runtime_error("tryxlist.hpp : line 37,list already exists.\n");
      }

      void display() {
        Node* temp = root;
        while(temp != nullptr) {
          std::cout<<"Parameter one is: "<<temp->_name<<std::endl
                   <<"Parameter two is: "<<temp->_data<<std::endl;
          temp = temp->next;
        }
      }

      int size() const {
        Node* temp = root;
        int count = 0;
        while(temp != nullptr) {
          ++count; temp = temp->next;
        }
        return count;
      }

      int search(T searchItem) {
        if(root != nullptr) {
          Node* current = root;
          int pos = 0;
          while(current != nullptr) {
            if(current->_name == searchItem)
              return pos;
            ++pos;
            current = current->next;
          }
        }
        else throw std::runtime_error("tryxlist.hpp : line 76, searching on an empty list.\n");
      }

      void reverse() {
        Node* prev   = nullptr;
        Node* current = root;
        Node* next;
        while (current != nullptr)
        {
          next  = current->next;
          current->next = prev;
          prev = current;
          current = next;
        }
        root = prev;
      }

      void unique_it() {
        Node *ptr1, *ptr2, *dup;
        ptr1 = root;

        while (ptr1 != nullptr && ptr1->next != nullptr)
        {
          ptr2 = ptr1;

          while (ptr2->next != nullptr)
          {
            if (ptr1->data == ptr2->next->data)
            {
              dup = ptr2->next;
              ptr2->next = ptr2->next->next;
              delete dup;
            }
            else ptr2 = ptr2->next;
          }
          ptr1 = ptr1->next;
        }
      }

      void push_back(T param1,U param2) {
        if(root != nullptr) {
          Node* nn = new Node(param1,param2);
          nn->next = root;
          root = nn;
        }
        else throw std::runtime_error("tryxlist.hpp : line 120,list has not been created.\n");
      }

      void pop_back() {
        if(root != nullptr) {
          Node *temp, *prev;
          temp = prev = root;
          while(temp->next != nullptr) {
            prev = temp;
            temp = temp->next;
          }
          prev->next =nullptr;
          delete prev; prev = nullptr;
        }
        else throw std::runtime_error("tryxlist.hpp : line 129,list has not been created.\n");
      }

      void pop(T param1) {
        Node *old, *current;
        current = root;
        if(root != nullptr) {
          while(current != nullptr) {
            if(current->_name == param1) {
              if(current == root)
                root = current->next;
              else old->next = current->next;
              delete current; current = nullptr;
              return;
            }
            else {
              old = current;
              current = current->next;
            }
          }
        }
        else throw std::runtime_error("tryxlist.hpp : line 145,parameter to be deleted not found.");
      }

    private:

      void deleteList() {
        Node* current = root;
        Node* next;
        while (current != NULL) {
         next = current->next;
         delete current;
         current = next;
        }
        root = nullptr;
      }

      struct Node {
        T _name;
        U _data;
        Node* next;

        Node() {}
        Node(T t,U u) : _name(t), _data(u) {}
        Node(const Node* other) {
          try {
            _name = other._name;
            _data = other._data;
            next = other.next;
          }
          catch(std::exception& e){ std::cerr<<"tryxlist.hpp : line 173,caught exception: "<<e.what(); }
        }
        Node* operator=(const Node* other) {
          try {
            Node* tmp_node = new Node(other);
            delete next;
            next = tmp_node;
            return *this;
          }
          catch(std::exception& e){ std::cerr<<"tryxlist.hpp : line 181,caught exception: "<<e.what(); }
        }

        ~Node() {}
      };

      Node* root;
  };

};

#endif
<commit_msg>Fixed various issues in the linked list.<commit_after>///////////////////////////////////////////////////////////////////////////////////
// Tryx Plugin System made by Avra Neel Chakraborty                              //
//                                                                               //
// Copyright (c) 2017 Avra Neel Chakraborty                                      //
//                                                                               //
// Permission is hereby granted, free of charge, to any person obtaining a copy  //
// of this software and associated documentation files (the "Software"), to deal //
// in the Software without restriction, including without limitation the rights  //
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell     //
// copies of the Software, and to permit persons to whom the Software is         //
// furnished to do so, subject to the following conditions:                      //
//                                                                               //
// The above copyright notice and this permission notice shall be included in    //
// all copies or substantial portions of the Software.                           //
///////////////////////////////////////////////////////////////////////////////////

#ifndef TRYX_LINKEDLIST_HPP
#define TRYX_LINKEDLIST_HPP

#include <stdexcept>

namespace Tryx {

  template<typename T,typename U>
  class TryxList {
    public:
      TryxList() {
        root = nullptr;
      }

      ~TryxList() { deleteList(); }

      void create(T param1,U param2) {
        if(root == nullptr) {
          Node* nn = new Node(param1,param2);
          root = nn;
        }
        else throw std::runtime_error("tryxlist.hpp : line 18,list already exists.\n");
      }

      void display() {
        Node* temp = root;
        while(temp->next != nullptr) {
          std::cout<<"Parameter one is: "<<temp->_name<<std::endl
                   <<"Parameter two is: "<<temp->_data<<std::endl;
          temp = temp->next;
        }
      }

      int size() const {
        Node* temp = root;
        int count = 0;
        while(temp->next != nullptr) {
          count++; temp = temp->next;
        }
        return count;
      }

      int search(T searchItem) {
        if(root != nullptr) {
          Node* current = root;
          int pos = 0;
          while(current != nullptr) {
            if(current->_name == searchItem)
              return pos;
            ++pos;
            current = current->next;
          }
        }
        else throw std::runtime_error("tryxlist.hpp : line 44, searching on an empty list.\n");
      }

      void reverse() {
        Node* prev   = nullptr;
        Node* current = root;
        Node* next;
        while(current != nullptr)
        {
          next = current->next;
          current->next = prev;
          prev = current;
          current = next;
        }
        root = prev;
      }

      void unique_it() {
        Node *ptr1, *ptr2, *dup;
        ptr1 = root;

        while (ptr1 != nullptr && ptr1->next != nullptr)
        {
          ptr2 = ptr1;

          while (ptr2->next != nullptr)
          {
            if (ptr1->data == ptr2->next->data)
            {
              dup = ptr2->next;
              ptr2->next = ptr2->next->next;
              delete dup;
            }
            else ptr2 = ptr2->next;
          }
          ptr1 = ptr1->next;
        }
      }

      void push_back(T param1,U param2) {
        if(root != nullptr) {
          Node* nn = new Node(param1,param2);
          Node* temp = root;
          while(temp->next != nullptr) temp = temp->next;
          temp->next = nn; nn->next = nullptr;
        }
        else create(param1,param2);
      }

      void pop_back() {
        if(root != nullptr) {
          Node* current = root;
          Node* prev;
          while(1) {
            if(current->next == nullptr)
            break;
            prev = current;
            current = current->next;
          }
          std::cout<<"Prev: "<<prev->_data<<std::endl;
          prev->next = nullptr;
          delete current;
        }
        else throw std::runtime_error("tryxlist.hpp : line 104,list has not been created.\n");
      }

      void pop(T param1) {
        Node *old, *current;
        current = root;
        if(root != nullptr) {
          while(current != nullptr) {
            if(current->_name == param1) {
              if(current == root)
                root = current->next;
              else old->next = current->next;
              delete current; current = nullptr;
              return;
            }
            else {
              old = current;
              current = current->next;
            }
          }
        }
        else throw std::runtime_error("tryxlist.hpp : line 121,parameter to be deleted not found.");
      }

    private:

      void deleteList() {
        Node* current = root;
        Node* next;
        while (current != nullptr) {
         next = current->next;
         delete current;
         current = next;
        }
        root = nullptr;
      }

      struct Node {
        T _name;
        U _data;
        Node* next;

        Node() {}
        Node(T t,U u) : _name(t), _data(u) {}
        Node(const Node* other) {
          try {
            _name = other._name;
            _data = other._data;
            next = other.next;
          }
          catch(std::exception& e){ std::cerr<<"tryxlist.hpp : line 162,caught exception: "<<e.what(); }
        }
        Node* operator=(const Node* other) {
          try {
            free();
            Node* temp = new Node(other);
            return temp;
          }
          catch(std::exception& e){ std::cerr<<"tryxlist.hpp : line 170,caught exception: "<<e.what(); }
        }
        void free() {
        delete next;
        }
        ~Node() {}
      };

      Node* root;
  };

};

#endif
<|endoftext|>


<commit_before>// This deletes a file written using write_file_(non)blocking

#include <stdio.h>
#include <glog/logging.h>
#include <sys/fcntl.h>
#include <sys/mman.h>

#include "protobufutil/message_stream.h"

#include "connection_options.h"
#include "hmac_provider.h"
#include "kinetic_connection_factory.h"
#include "value_factory.h"
#include "socket_wrapper.h"

using com::seagate::kinetic::HmacProvider;
using com::seagate::kinetic::proto::Message;
using com::seagate::kinetic::proto::Message_MessageType_GET;
using com::seagate::kinetic::proto::Message_Algorithm_SHA1;
using com::seagate::kinetic::ValueFactory;
using kinetic::KineticConnection;
using kinetic::KineticConnectionFactory;
using kinetic::Status;
using kinetic::KineticRecord;
using kinetic::DeleteCallbackInterface;
using kinetic::NonblockingError;
using palominolabs::protobufutil::MessageStreamFactory;

class DeleteCallback : public DeleteCallbackInterface {
public:
    DeleteCallback(int* remaining) : remaining_(remaining) {};
    void Success() {
        printf(".");
        fflush(stdout);
        (*remaining_)--;
    }

    void Failure(NonblockingError error) {
        printf("Error!\n");
        exit(1);
    }
private:
    int* remaining_;

};

int main(int argc, char* argv[]) {

    if (argc != 3) {
        printf("%s: <host> <kinetic key>\n", argv[0]);
        return 1;
    }

    const char* host = argv[1];
    const char* kinetic_key = argv[2];

    kinetic::ConnectionOptions options;
    options.host = host;
    options.port = 8123;
    options.user_id = 1;
    options.hmac_key = "asdfasdf";

    HmacProvider hmac_provider;
    ValueFactory value_factory;
    MessageStreamFactory message_stream_factory(NULL, value_factory);
    kinetic::KineticConnectionFactory kinetic_connection_factory(hmac_provider,
            message_stream_factory);

    kinetic::KineticConnection* kinetic_connection;
    if(!kinetic_connection_factory.NewConnection(options, &kinetic_connection).ok()) {
        printf("Unable to connect\n");
        return 1;
    }

    std::string value;
    if(!kinetic_connection->Get(kinetic_key, &value, NULL, NULL).ok()) {
        printf("Unable to get metadata\n");
        return 1;
    }

    unsigned int file_size = std::stoi(value);
    printf("Deleting file of size %d\n", file_size);

    delete kinetic_connection;

    kinetic::NonblockingKineticConnection* connection;
    kinetic_connection_factory.NewNonblockingConnection(options, &connection);

    char key_buffer[100];
    int remaining = 0;
    for (unsigned int i = 0; i < file_size; i += 1024*1024) {
        unsigned int block_length = 1024*1024;
        if (i + block_length > file_size) {
            block_length = file_size - i + 1;
        }

        sprintf(key_buffer, "%s-%10d", kinetic_key, i);
        remaining++;
        DeleteCallback* callback = new DeleteCallback(&remaining);
        std::string key(key_buffer);
        connection->Delete(key, "", true, callback);
    }

    remaining++;
    connection->Delete(kinetic_key, "", true, new DeleteCallback(&remaining));

    fd_set read_fds, write_fds;
    int num_fds = 0;
    connection->Run(&read_fds, &write_fds, &num_fds);
    while (remaining > 0) {
        connection->Run(&read_fds, &write_fds, &num_fds);
    }

    printf("\nDone!\n");

    delete connection;

    return 0;
}
<commit_msg>Fixed a trivial build failure caused by a change to the client library<commit_after>// This deletes a file written using write_file_(non)blocking

#include <stdio.h>
#include <glog/logging.h>
#include <sys/fcntl.h>
#include <sys/mman.h>

#include "protobufutil/message_stream.h"

#include "connection_options.h"
#include "hmac_provider.h"
#include "kinetic_connection_factory.h"
#include "value_factory.h"
#include "socket_wrapper.h"

using com::seagate::kinetic::HmacProvider;
using com::seagate::kinetic::proto::Message;
using com::seagate::kinetic::proto::Message_MessageType_GET;
using com::seagate::kinetic::proto::Message_Algorithm_SHA1;
using com::seagate::kinetic::ValueFactory;
using kinetic::KineticConnection;
using kinetic::KineticConnectionFactory;
using kinetic::KineticRecord;
using kinetic::NonblockingError;
using kinetic::SimpleCallbackInterface;
using kinetic::Status;
using palominolabs::protobufutil::MessageStreamFactory;

class DeleteCallback : public SimpleCallbackInterface {
public:
    DeleteCallback(int* remaining) : remaining_(remaining) {};
    void Success() {
        printf(".");
        fflush(stdout);
        (*remaining_)--;
    }

    void Failure(NonblockingError error) {
        printf("Error!\n");
        exit(1);
    }
private:
    int* remaining_;

};

int main(int argc, char* argv[]) {

    if (argc != 3) {
        printf("%s: <host> <kinetic key>\n", argv[0]);
        return 1;
    }

    const char* host = argv[1];
    const char* kinetic_key = argv[2];

    kinetic::ConnectionOptions options;
    options.host = host;
    options.port = 8123;
    options.user_id = 1;
    options.hmac_key = "asdfasdf";

    HmacProvider hmac_provider;
    ValueFactory value_factory;
    MessageStreamFactory message_stream_factory(NULL, value_factory);
    kinetic::KineticConnectionFactory kinetic_connection_factory(hmac_provider,
            message_stream_factory);

    kinetic::KineticConnection* kinetic_connection;
    if(!kinetic_connection_factory.NewConnection(options, &kinetic_connection).ok()) {
        printf("Unable to connect\n");
        return 1;
    }

    std::string value;
    if(!kinetic_connection->Get(kinetic_key, &value, NULL, NULL).ok()) {
        printf("Unable to get metadata\n");
        return 1;
    }

    unsigned int file_size = std::stoi(value);
    printf("Deleting file of size %d\n", file_size);

    delete kinetic_connection;

    kinetic::NonblockingKineticConnection* connection;
    kinetic_connection_factory.NewNonblockingConnection(options, &connection);

    char key_buffer[100];
    int remaining = 0;
    for (unsigned int i = 0; i < file_size; i += 1024*1024) {
        unsigned int block_length = 1024*1024;
        if (i + block_length > file_size) {
            block_length = file_size - i + 1;
        }

        sprintf(key_buffer, "%s-%10d", kinetic_key, i);
        remaining++;
        DeleteCallback* callback = new DeleteCallback(&remaining);
        std::string key(key_buffer);
        connection->Delete(key, "", true, callback);
    }

    remaining++;
    connection->Delete(kinetic_key, "", true, new DeleteCallback(&remaining));

    fd_set read_fds, write_fds;
    int num_fds = 0;
    connection->Run(&read_fds, &write_fds, &num_fds);
    while (remaining > 0) {
        connection->Run(&read_fds, &write_fds, &num_fds);
    }

    printf("\nDone!\n");

    delete connection;

    return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013, 2018-2019 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Stan Czerniawski
 */

#include "dev/arm/smmu_v3_cmdexec.hh"

#include "base/bitfield.hh"
#include "dev/arm/smmu_v3.hh"

void
SMMUCommandExecProcess::main(Yield &yield)
{
    SMMUAction a;
    a.type = ACTION_INITIAL_NOP;
    a.pkt = NULL;
    a.ifc = nullptr;
    a.delay = 0;
    yield(a);

    while (true) {
        busy = true;

        while (true) {
            int sizeMask = mask(smmu.regs.cmdq_base & Q_BASE_SIZE_MASK);

            if ((smmu.regs.cmdq_cons & sizeMask) ==
                    (smmu.regs.cmdq_prod & sizeMask))
                break; // command queue empty

            Addr cmdAddr =
                (smmu.regs.cmdq_base & Q_BASE_ADDR_MASK) +
                (smmu.regs.cmdq_cons & sizeMask) * sizeof(SMMUCommand);

            // This deliberately resets the error field in cmdq_cons!
            smmu.regs.cmdq_cons = (smmu.regs.cmdq_cons + 1) & sizeMask;

            doRead(yield, cmdAddr, &cmd, sizeof(SMMUCommand));
            smmu.processCommand(cmd);
        }

        busy = false;
        // No more commands to process, signal the SMMU as drained
        smmu.signalDrainDone();

        doSleep(yield);
    }
}
<commit_msg>dev-arm: Fix SMMUv3 CMDQ wrapping<commit_after>/*
 * Copyright (c) 2013, 2018-2019 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Stan Czerniawski
 */

#include "dev/arm/smmu_v3_cmdexec.hh"

#include "base/bitfield.hh"
#include "dev/arm/smmu_v3.hh"

void
SMMUCommandExecProcess::main(Yield &yield)
{
    SMMUAction a;
    a.type = ACTION_INITIAL_NOP;
    a.pkt = NULL;
    a.ifc = nullptr;
    a.delay = 0;
    yield(a);

    while (true) {
        busy = true;

        while (true) {
            // Masking depending on CMDQ_BASE.LOG2SIZE (log(number of
            // queue entries)). Example: a value of 0b101 (32 entries)
            // generates a 0b11111 mask.
            int size_mask = mask(
                smmu.regs.cmdq_base & Q_BASE_SIZE_MASK);

            // In this case the wrap bit is considered (+1)
            int size_mask_wrap = mask(
                (smmu.regs.cmdq_base & Q_BASE_SIZE_MASK) + 1);

            if ((smmu.regs.cmdq_cons & size_mask_wrap) ==
                    (smmu.regs.cmdq_prod & size_mask_wrap))
                break; // command queue empty

            Addr cmd_addr =
                (smmu.regs.cmdq_base & Q_BASE_ADDR_MASK) +
                (smmu.regs.cmdq_cons & size_mask) * sizeof(SMMUCommand);

            // This deliberately resets the error field in cmdq_cons!
            smmu.regs.cmdq_cons = (smmu.regs.cmdq_cons + 1) & size_mask_wrap;

            doRead(yield, cmd_addr, &cmd, sizeof(SMMUCommand));
            smmu.processCommand(cmd);
        }

        busy = false;
        // No more commands to process, signal the SMMU as drained
        smmu.signalDrainDone();

        doSleep(yield);
    }
}
<|endoftext|>


<commit_before>/* bzflag
 * Copyright (c) 1993 - 2004 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

/* common headers */
#include "common.h"

/* interface header */
#include "WinJoystick.h"

/* implementation headers */
#include <mmsystem.h>
#include "ErrorHandler.h"
#include "TextUtils.h"

WinJoystick::WinJoystick() : inited(false)
{
}

WinJoystick::~WinJoystick()
{
}

void	      WinJoystick::initJoystick(const char* joystickName)
{
  inited = false;

  if (!strcmp(joystickName, "off") || !strcmp(joystickName, "")) {
    return;
  }

  if (strlen(joystickName) < 11) {
    printError("Invalid joystick name.");
    return;
  }

  if (joystickName[10] == '1')
    JoystickID = JOYSTICKID1;
  else if (joystickName[10] == '2')
    JoystickID = JOYSTICKID2;

  JOYINFO joyInfo;
  JOYCAPS joyCaps;
  if ((joyGetPos(JoystickID, &joyInfo) != JOYERR_NOERROR) ||
      (joyGetDevCaps(JoystickID, &joyCaps, sizeof(joyCaps)) != JOYERR_NOERROR)) {
    printError("Unable to initialize joystick.  Perhaps it is not plugged in?");
    return;
  }

  xMin = (float)joyCaps.wXmin;
  xMax = (float)joyCaps.wXmax;
  yMin = (float)joyCaps.wYmin;
  yMax = (float)joyCaps.wYmax;

  inited = true;
}

bool	      WinJoystick::joystick() const
{
  return inited;
}

void	      WinJoystick::getJoy(int& x, int& y) const
{
  if (!inited)
    return;

  JOYINFOEX joyInfo;
  // we're only interested in position
  joyInfo.dwFlags = JOY_RETURNX | JOY_RETURNY | JOY_USEDEADZONE;
  joyInfo.dwSize = sizeof(joyInfo);

  // check for errors
  if (joyGetPosEx(JoystickID, &joyInfo) != JOYERR_NOERROR) {
    printError("Could not get extended info from joystick");
    return;
  }

  // adjust X and Y to scale
  x = (joyInfo.dwXpos / xMax) * 2000 - 1000;
  y = (joyInfo.dwYpos / yMax) * 2000 - 1000;

  // ballistic
  x = (x * abs(x)) / 1000;
  y = (y * abs(y)) / 1000;

}

unsigned long WinJoystick::getJoyButtons() const
{
  if (!inited)
    return 0;

  JOYINFOEX joyInfo;
  // we're only interested in buttons
  joyInfo.dwFlags = JOY_RETURNBUTTONS;
  joyInfo.dwSize = sizeof(joyInfo);

  // check for errors
  if (joyGetPosEx(JoystickID, &joyInfo) != JOYERR_NOERROR) {
    printError("Could not get extended info from joystick");
    return 0;
  }

  unsigned long retbuts = joyInfo.dwButtons;
  unsigned long buttons = 0;
  if (retbuts & JOY_BUTTON1)  buttons = buttons | 0x00001;
  if (retbuts & JOY_BUTTON2)  buttons = buttons | 0x00002;
  if (retbuts & JOY_BUTTON3)  buttons = buttons | 0x00004;
  if (retbuts & JOY_BUTTON4)  buttons = buttons | 0x00008;
  if (retbuts & JOY_BUTTON5)  buttons = buttons | 0x00010;
  if (retbuts & JOY_BUTTON6)  buttons = buttons | 0x00020;
  if (retbuts & JOY_BUTTON7)  buttons = buttons | 0x00040;
  if (retbuts & JOY_BUTTON8)  buttons = buttons | 0x00080;
  if (retbuts & JOY_BUTTON9)  buttons = buttons | 0x00100;
  if (retbuts & JOY_BUTTON10) buttons = buttons | 0x00200;

  return buttons;
}

void	      WinJoystick::getJoyDevices(std::vector<std::string> &list) const
{
  list.clear();
  if (joyGetNumDevs() != 0) {
    // we have at least one joystick driver, get the name of both joystick IDs if they exist.
    JOYCAPS joyCaps;
    if (joyGetDevCaps(JOYSTICKID1, &joyCaps, sizeof(joyCaps)) == JOYERR_NOERROR) {
      list.push_back(string_util::format("Joystick 1 (%s)", joyCaps.szPname));
    }
    if (joyGetDevCaps(JOYSTICKID2, &joyCaps, sizeof(joyCaps)) == JOYERR_NOERROR) {
      list.push_back(string_util::format("Joystick 2 (%s)", joyCaps.szPname));
    }
  }
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<commit_msg>quell MingW warning<commit_after>/* bzflag
 * Copyright (c) 1993 - 2004 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

/* common headers */
#include "common.h"

/* interface header */
#include "WinJoystick.h"

/* implementation headers */
#include <mmsystem.h>
#include "ErrorHandler.h"
#include "TextUtils.h"

WinJoystick::WinJoystick() : inited(false)
{
}

WinJoystick::~WinJoystick()
{
}

void	      WinJoystick::initJoystick(const char* joystickName)
{
  inited = false;

  if (!strcmp(joystickName, "off") || !strcmp(joystickName, "")) {
    return;
  }

  if (strlen(joystickName) < 11) {
    printError("Invalid joystick name.");
    return;
  }

  if (joystickName[10] == '1')
    JoystickID = JOYSTICKID1;
  else if (joystickName[10] == '2')
    JoystickID = JOYSTICKID2;

  JOYINFO joyInfo;
  JOYCAPS joyCaps;
  if ((joyGetPos(JoystickID, &joyInfo) != JOYERR_NOERROR) ||
      (joyGetDevCaps(JoystickID, &joyCaps, sizeof(joyCaps)) != JOYERR_NOERROR)) {
    printError("Unable to initialize joystick.  Perhaps it is not plugged in?");
    return;
  }

  xMin = (float)joyCaps.wXmin;
  xMax = (float)joyCaps.wXmax;
  yMin = (float)joyCaps.wYmin;
  yMax = (float)joyCaps.wYmax;

  inited = true;
}

bool	      WinJoystick::joystick() const
{
  return inited;
}

void	      WinJoystick::getJoy(int& x, int& y) const
{
  if (!inited)
    return;

  JOYINFOEX joyInfo;
  // we're only interested in position
  joyInfo.dwFlags = JOY_RETURNX | JOY_RETURNY | JOY_USEDEADZONE;
  joyInfo.dwSize = sizeof(joyInfo);

  // check for errors
  if (joyGetPosEx(JoystickID, &joyInfo) != JOYERR_NOERROR) {
    printError("Could not get extended info from joystick");
    return;
  }

  // adjust X and Y to scale
  x = (int)((joyInfo.dwXpos / xMax) * 2000 - 1000);
  y = (int)((joyInfo.dwYpos / yMax) * 2000 - 1000);

  // ballistic
  x = (x * abs(x)) / 1000;
  y = (y * abs(y)) / 1000;

}

unsigned long WinJoystick::getJoyButtons() const
{
  if (!inited)
    return 0;

  JOYINFOEX joyInfo;
  // we're only interested in buttons
  joyInfo.dwFlags = JOY_RETURNBUTTONS;
  joyInfo.dwSize = sizeof(joyInfo);

  // check for errors
  if (joyGetPosEx(JoystickID, &joyInfo) != JOYERR_NOERROR) {
    printError("Could not get extended info from joystick");
    return 0;
  }

  unsigned long retbuts = joyInfo.dwButtons;
  unsigned long buttons = 0;
  if (retbuts & JOY_BUTTON1)  buttons = buttons | 0x00001;
  if (retbuts & JOY_BUTTON2)  buttons = buttons | 0x00002;
  if (retbuts & JOY_BUTTON3)  buttons = buttons | 0x00004;
  if (retbuts & JOY_BUTTON4)  buttons = buttons | 0x00008;
  if (retbuts & JOY_BUTTON5)  buttons = buttons | 0x00010;
  if (retbuts & JOY_BUTTON6)  buttons = buttons | 0x00020;
  if (retbuts & JOY_BUTTON7)  buttons = buttons | 0x00040;
  if (retbuts & JOY_BUTTON8)  buttons = buttons | 0x00080;
  if (retbuts & JOY_BUTTON9)  buttons = buttons | 0x00100;
  if (retbuts & JOY_BUTTON10) buttons = buttons | 0x00200;

  return buttons;
}

void	      WinJoystick::getJoyDevices(std::vector<std::string> &list) const
{
  list.clear();
  if (joyGetNumDevs() != 0) {
    // we have at least one joystick driver, get the name of both joystick IDs if they exist.
    JOYCAPS joyCaps;
    if (joyGetDevCaps(JOYSTICKID1, &joyCaps, sizeof(joyCaps)) == JOYERR_NOERROR) {
      list.push_back(string_util::format("Joystick 1 (%s)", joyCaps.szPname));
    }
    if (joyGetDevCaps(JOYSTICKID2, &joyCaps, sizeof(joyCaps)) == JOYERR_NOERROR) {
      list.push_back(string_util::format("Joystick 2 (%s)", joyCaps.szPname));
    }
  }
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<|endoftext|>


<commit_before>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2014 Ulrich von Zadow
//
//  This library 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; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#include "DisplayEngine.h"
#include "../avgconfigwrapper.h"

#ifdef __APPLE__
#include "SDLMain.h"
#endif

#include "Event.h"
#include "MouseEvent.h"
#include "KeyEvent.h"
#include "SDLWindow.h"
#ifndef AVG_ENABLE_EGL
  #include "SecondaryWindow.h"
#endif

#include "../base/Exception.h"
#include "../base/Logger.h"
#include "../base/ScopeTimer.h"
#include "../base/TimeSource.h"

#include "../graphics/Display.h"

#include "../video/VideoDecoder.h"

#ifdef __APPLE__
#include <ApplicationServices/ApplicationServices.h>
#endif

#include <SDL/SDL.h>

#ifdef __APPLE__
#include <OpenGL/OpenGL.h>
#endif

#ifdef AVG_ENABLE_XINERAMA
#include <X11/extensions/Xinerama.h>
#endif

#include <signal.h>
#include <iostream>

#ifdef _WIN32
#include <windows.h>
#endif

using namespace std;

namespace avg {

void DisplayEngine::initSDL()
{
#ifdef __APPLE__
    static bool bSDLInitialized = false;
    if (!bSDLInitialized) {
        CustomSDLMain();
        bSDLInitialized = true;
    }
#endif
#ifdef linux
    // Disable all other video drivers (DirectFB, libcaca, ...) to avoid confusing
    // error messages.
    SDL_putenv((char*)"SDL_VIDEODRIVER=x11");
#endif
    int err = SDL_InitSubSystem(SDL_INIT_VIDEO);
    if (err == -1) {
        throw Exception(AVG_ERR_VIDEO_INIT_FAILED, SDL_GetError());
    }
}

void DisplayEngine::quitSDL()
{
#ifndef _WIN32
    SDL_QuitSubSystem(SDL_INIT_VIDEO);
#endif
}

DisplayEngine::DisplayEngine()
    : InputDevice("DisplayEngine"),
      m_Size(0,0),
      m_NumFrames(0),
      m_VBRate(0),
      m_Framerate(60),
      m_bInitialized(false),
      m_EffFramerate(0)
{
    initSDL();

    m_Gamma[0] = 1.0;
    m_Gamma[1] = 1.0;
    m_Gamma[2] = 1.0;
}

DisplayEngine::~DisplayEngine()
{
}

void DisplayEngine::init(const DisplayParams& dp, GLConfig glConfig)
{
    if (m_Gamma[0] != 1.0f || m_Gamma[1] != 1.0f || m_Gamma[2] != 1.0f) {
        internalSetGamma(1.0f, 1.0f, 1.0f);
    }

    m_pWindows.push_back(WindowPtr(new SDLWindow(dp, glConfig)));
    #ifndef AVG_ENABLE_EGL
    for (int i=1; i<dp.getNumWindows(); ++i) {
        m_pWindows.push_back(WindowPtr(new SecondaryWindow(dp.getWindowParams(i),
                dp.isFullscreen(), glConfig)));
    }
    #endif

    Display::get()->getRefreshRate();

    setGamma(dp.getGamma(0), dp.getGamma(1), dp.getGamma(2));
    showCursor(dp.isCursorVisible());
    if (dp.getFramerate() == 0) {
        setVBlankRate(dp.getVBRate());
    } else {
        setFramerate(dp.getFramerate());
    }

    // SDL sets up a signal handler we really don't want.
    signal(SIGSEGV, SIG_DFL);
    VideoDecoder::logConfig();

    SDL_EnableUNICODE(1);
}

void DisplayEngine::teardown()
{
    m_pWindows.clear();
}

void DisplayEngine::initRender()
{
    m_NumFrames = 0;
    m_FramesTooLate = 0;
    m_TimeSpentWaiting = 0;
    m_StartTime = TimeSource::get()->getCurrentMicrosecs();
    m_LastFrameTime = m_StartTime;
    m_bInitialized = true;
    if (m_VBRate != 0) {
        setVBlankRate(m_VBRate);
    } else {
        setFramerate(m_Framerate);
    }
}

void DisplayEngine::deinitRender()
{
    AVG_TRACE(Logger::category::PROFILE, Logger::severity::INFO,
            "Framerate statistics: ");
    AVG_TRACE(Logger::category::PROFILE, Logger::severity::INFO,
            "  Total frames: " <<m_NumFrames);
    float TotalTime = float(TimeSource::get()->getCurrentMicrosecs()
            -m_StartTime)/1000000;
    AVG_TRACE(Logger::category::PROFILE,  Logger::severity::INFO,
            "  Total time: " << TotalTime << " seconds");
    float actualFramerate = (m_NumFrames+1)/TotalTime;
    AVG_TRACE(Logger::category::PROFILE,  Logger::severity::INFO,
            "  Framerate achieved: " << actualFramerate);
    AVG_TRACE(Logger::category::PROFILE,  Logger::severity::INFO,
            "  Frames too late: " << m_FramesTooLate);
    AVG_TRACE(Logger::category::PROFILE,  Logger::severity::INFO,
            "  Percent of time spent waiting: "
            << float (m_TimeSpentWaiting)/(10000*TotalTime));
    if (m_Framerate != 0) {
        AVG_TRACE(Logger::category::PROFILE,  Logger::severity::INFO,
                "  Framerate goal was: " << m_Framerate);
        if (m_Framerate*2 < actualFramerate && m_NumFrames > 10) {
            AVG_LOG_WARNING("Actual framerate was a lot higher than framerate goal.\
                    Is vblank sync forced off?");
        }
    }
    m_bInitialized = false;
}

void DisplayEngine::setFramerate(float rate)
{
    if (rate != 0 && m_bInitialized) {
        for (unsigned i=0; i<m_pWindows.size(); ++i) {
            GLContext* pContext = m_pWindows[i]->getGLContext();
            pContext->activate();
            pContext->initVBlank(0);
        }
    }
    m_Framerate = rate;
    m_VBRate = 0;
}

float DisplayEngine::getFramerate()
{
    return m_Framerate;
}

float DisplayEngine::getEffectiveFramerate()
{
    return m_EffFramerate;
}

void DisplayEngine::setVBlankRate(int rate)
{
    m_VBRate = rate;
    if (m_bInitialized) {
        GLContext* pContext = m_pWindows[0]->getGLContext();
        pContext->activate();
        bool bOK = pContext->initVBlank(rate);
        m_Framerate = Display::get()->getRefreshRate()/m_VBRate;
        if (!bOK || rate == 0) {
            AVG_LOG_WARNING("Using framerate of " << m_Framerate <<
                    " instead of VBRate of " << m_VBRate);
            m_VBRate = 0;
        }
    }
}

bool DisplayEngine::wasFrameLate()
{
    return m_bFrameLate;
}

void DisplayEngine::setGamma(float red, float green, float blue)
{
    if (red > 0) {
        bool bOk = internalSetGamma(red, green, blue);
        m_Gamma[0] = red;
        m_Gamma[1] = green;
        m_Gamma[2] = blue;
        if (!bOk) {
            AVG_LOG_WARNING("Unable to set display gamma.");
        }
    }
}

void DisplayEngine::setMousePos(const IntPoint& pos)
{
    SDL_WarpMouse(pos.x, pos.y);
}

int DisplayEngine::getKeyModifierState() const
{
    return SDL_GetModState();
}

void DisplayEngine::setWindowTitle(const string& sTitle)
{
    SDL_WM_SetCaption(sTitle.c_str(), 0);
}

unsigned DisplayEngine::getNumWindows() const
{
    return m_pWindows.size();
}

const WindowPtr DisplayEngine::getWindow(unsigned i) const
{
    return m_pWindows[i];
}

SDLWindowPtr DisplayEngine::getSDLWindow() const
{
    return boost::dynamic_pointer_cast<SDLWindow>(m_pWindows[0]);
}

static ProfilingZoneID WaitProfilingZone("Render - wait");

void DisplayEngine::frameWait()
{
    ScopeTimer Timer(WaitProfilingZone);

    m_NumFrames++;

    m_FrameWaitStartTime = TimeSource::get()->getCurrentMicrosecs();
    m_TargetTime = m_LastFrameTime+(long long)(1000000/m_Framerate);
    m_bFrameLate = false;
    if (m_VBRate == 0) {
        if (m_FrameWaitStartTime <= m_TargetTime) {
            long long WaitTime = (m_TargetTime-m_FrameWaitStartTime)/1000;
            if (WaitTime > 5000) {
                AVG_LOG_WARNING("DisplayEngine: waiting " << WaitTime << " ms.");
            }
            TimeSource::get()->sleepUntil(m_TargetTime/1000);
        }
    }
}

void DisplayEngine::swapBuffers()
{
    for (unsigned i=0; i<m_pWindows.size(); ++i) {
        m_pWindows[i]->swapBuffers();
    }
}

void DisplayEngine::checkJitter()
{
    if (m_LastFrameTime == 0) {
        m_EffFramerate = 0;
    } else {
        long long curIntervalTime = TimeSource::get()->getCurrentMicrosecs()
                -m_LastFrameTime;
        m_EffFramerate = 1000000.0f/curIntervalTime;
    }

    long long frameTime = TimeSource::get()->getCurrentMicrosecs();
    int maxDelay;
    if (m_VBRate == 0) {
        maxDelay = 2;
    } else {
        maxDelay = 6;
    }
    if ((frameTime - m_TargetTime)/1000 > maxDelay || m_bFrameLate) {
        m_bFrameLate = true;
        m_FramesTooLate++;
    }

    m_LastFrameTime = frameTime;
    m_TimeSpentWaiting += m_LastFrameTime-m_FrameWaitStartTime;
//    cerr << m_LastFrameTime << ", m_FrameWaitStartTime=" << m_FrameWaitStartTime << endl;
//    cerr << m_TimeSpentWaiting << endl;
}

long long DisplayEngine::getDisplayTime()
{
    return (m_LastFrameTime-m_StartTime)/1000;
}

const IntPoint& DisplayEngine::getSize() const
{
    return m_Size;
}

IntPoint DisplayEngine::getWindowSize() const
{
    if (m_pWindows.empty()) {
        return IntPoint(0,0);
    } else {
        return m_pWindows[0]->getSize();
    }
}

bool DisplayEngine::isFullscreen() const
{
    AVG_ASSERT(!m_pWindows.empty());
    return m_pWindows[0]->isFullscreen();
}

void DisplayEngine::showCursor(bool bShow)
{
#ifdef _WIN32
#define MAX_CORE_POINTERS   6
    // Hack to fix a pointer issue with fullscreen, SDL and touchscreens
    // Refer to Mantis bug #140
    for (int i = 0; i < MAX_CORE_POINTERS; ++i) {
        ShowCursor(bShow);
    }
#else
    if (bShow) {
        SDL_ShowCursor(SDL_ENABLE);
    } else {
        SDL_ShowCursor(SDL_DISABLE);
    }
#endif
}

BitmapPtr DisplayEngine::screenshot(int buffer)
{
    IntRect destRect;
    for (unsigned i=0; i != m_pWindows.size(); ++i) {
        IntRect winDims(m_pWindows[i]->getPos(),
                m_pWindows[i]->getPos()+m_pWindows[i]->getSize());
        destRect.expand(winDims);
    }

    BitmapPtr pDestBmp;
    if(true) {
        pDestBmp = BitmapPtr(new Bitmap(destRect.size(), R8G8B8X8));
    }else {
        pDestBmp = BitmapPtr(new Bitmap(destRect.size(), B8G8R8X8));
    }
    for (unsigned i=0; i != m_pWindows.size(); ++i) {
        BitmapPtr pWinBmp = m_pWindows[i]->screenshot(buffer);
        IntPoint pos = m_pWindows[i]->getPos() - destRect.tl;
        pDestBmp->blt(*pWinBmp, pos);
    }
    return pDestBmp;
}

vector<EventPtr> DisplayEngine::pollEvents()
{
    vector<EventPtr> pEvents;
    for (unsigned i=0; i != m_pWindows.size(); ++i) {
        vector<EventPtr> pWinEvents =  m_pWindows[i]->pollEvents();
        pEvents.insert(pEvents.end(), pWinEvents.begin(), pWinEvents.end());
    }
    return pEvents;
}

bool DisplayEngine::internalSetGamma(float red, float green, float blue)
{
#ifdef __APPLE__
    // Workaround for broken SDL_SetGamma for libSDL 1.2.15 under Lion
    CGError err = CGSetDisplayTransferByFormula(kCGDirectMainDisplay, 0, 1, 1/red,
            0, 1, 1/green, 0, 1, 1/blue);
    return (err == CGDisplayNoErr);
#else
    int err = SDL_SetGamma(float(red), float(green), float(blue));
    return (err != -1);
#endif
}

}
<commit_msg>Fixed tests for non-gles build.<commit_after>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2014 Ulrich von Zadow
//
//  This library 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; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#include "DisplayEngine.h"
#include "../avgconfigwrapper.h"

#ifdef __APPLE__
#include "SDLMain.h"
#endif

#include "Event.h"
#include "MouseEvent.h"
#include "KeyEvent.h"
#include "SDLWindow.h"
#ifndef AVG_ENABLE_EGL
  #include "SecondaryWindow.h"
#endif

#include "../base/Exception.h"
#include "../base/Logger.h"
#include "../base/ScopeTimer.h"
#include "../base/TimeSource.h"

#include "../graphics/Display.h"
#include "../graphics/BitmapLoader.h"

#include "../video/VideoDecoder.h"

#ifdef __APPLE__
#include <ApplicationServices/ApplicationServices.h>
#endif

#include <SDL/SDL.h>

#ifdef __APPLE__
#include <OpenGL/OpenGL.h>
#endif

#ifdef AVG_ENABLE_XINERAMA
#include <X11/extensions/Xinerama.h>
#endif

#include <signal.h>
#include <iostream>

#ifdef _WIN32
#include <windows.h>
#endif

using namespace std;

namespace avg {

void DisplayEngine::initSDL()
{
#ifdef __APPLE__
    static bool bSDLInitialized = false;
    if (!bSDLInitialized) {
        CustomSDLMain();
        bSDLInitialized = true;
    }
#endif
#ifdef linux
    // Disable all other video drivers (DirectFB, libcaca, ...) to avoid confusing
    // error messages.
    SDL_putenv((char*)"SDL_VIDEODRIVER=x11");
#endif
    int err = SDL_InitSubSystem(SDL_INIT_VIDEO);
    if (err == -1) {
        throw Exception(AVG_ERR_VIDEO_INIT_FAILED, SDL_GetError());
    }
}

void DisplayEngine::quitSDL()
{
#ifndef _WIN32
    SDL_QuitSubSystem(SDL_INIT_VIDEO);
#endif
}

DisplayEngine::DisplayEngine()
    : InputDevice("DisplayEngine"),
      m_Size(0,0),
      m_NumFrames(0),
      m_VBRate(0),
      m_Framerate(60),
      m_bInitialized(false),
      m_EffFramerate(0)
{
    initSDL();

    m_Gamma[0] = 1.0;
    m_Gamma[1] = 1.0;
    m_Gamma[2] = 1.0;
}

DisplayEngine::~DisplayEngine()
{
}

void DisplayEngine::init(const DisplayParams& dp, GLConfig glConfig)
{
    if (m_Gamma[0] != 1.0f || m_Gamma[1] != 1.0f || m_Gamma[2] != 1.0f) {
        internalSetGamma(1.0f, 1.0f, 1.0f);
    }

    m_pWindows.push_back(WindowPtr(new SDLWindow(dp, glConfig)));
    #ifndef AVG_ENABLE_EGL
    for (int i=1; i<dp.getNumWindows(); ++i) {
        m_pWindows.push_back(WindowPtr(new SecondaryWindow(dp.getWindowParams(i),
                dp.isFullscreen(), glConfig)));
    }
    #endif

    Display::get()->getRefreshRate();

    setGamma(dp.getGamma(0), dp.getGamma(1), dp.getGamma(2));
    showCursor(dp.isCursorVisible());
    if (dp.getFramerate() == 0) {
        setVBlankRate(dp.getVBRate());
    } else {
        setFramerate(dp.getFramerate());
    }

    // SDL sets up a signal handler we really don't want.
    signal(SIGSEGV, SIG_DFL);
    VideoDecoder::logConfig();

    SDL_EnableUNICODE(1);
}

void DisplayEngine::teardown()
{
    m_pWindows.clear();
}

void DisplayEngine::initRender()
{
    m_NumFrames = 0;
    m_FramesTooLate = 0;
    m_TimeSpentWaiting = 0;
    m_StartTime = TimeSource::get()->getCurrentMicrosecs();
    m_LastFrameTime = m_StartTime;
    m_bInitialized = true;
    if (m_VBRate != 0) {
        setVBlankRate(m_VBRate);
    } else {
        setFramerate(m_Framerate);
    }
}

void DisplayEngine::deinitRender()
{
    AVG_TRACE(Logger::category::PROFILE, Logger::severity::INFO,
            "Framerate statistics: ");
    AVG_TRACE(Logger::category::PROFILE, Logger::severity::INFO,
            "  Total frames: " <<m_NumFrames);
    float TotalTime = float(TimeSource::get()->getCurrentMicrosecs()
            -m_StartTime)/1000000;
    AVG_TRACE(Logger::category::PROFILE,  Logger::severity::INFO,
            "  Total time: " << TotalTime << " seconds");
    float actualFramerate = (m_NumFrames+1)/TotalTime;
    AVG_TRACE(Logger::category::PROFILE,  Logger::severity::INFO,
            "  Framerate achieved: " << actualFramerate);
    AVG_TRACE(Logger::category::PROFILE,  Logger::severity::INFO,
            "  Frames too late: " << m_FramesTooLate);
    AVG_TRACE(Logger::category::PROFILE,  Logger::severity::INFO,
            "  Percent of time spent waiting: "
            << float (m_TimeSpentWaiting)/(10000*TotalTime));
    if (m_Framerate != 0) {
        AVG_TRACE(Logger::category::PROFILE,  Logger::severity::INFO,
                "  Framerate goal was: " << m_Framerate);
        if (m_Framerate*2 < actualFramerate && m_NumFrames > 10) {
            AVG_LOG_WARNING("Actual framerate was a lot higher than framerate goal.\
                    Is vblank sync forced off?");
        }
    }
    m_bInitialized = false;
}

void DisplayEngine::setFramerate(float rate)
{
    if (rate != 0 && m_bInitialized) {
        for (unsigned i=0; i<m_pWindows.size(); ++i) {
            GLContext* pContext = m_pWindows[i]->getGLContext();
            pContext->activate();
            pContext->initVBlank(0);
        }
    }
    m_Framerate = rate;
    m_VBRate = 0;
}

float DisplayEngine::getFramerate()
{
    return m_Framerate;
}

float DisplayEngine::getEffectiveFramerate()
{
    return m_EffFramerate;
}

void DisplayEngine::setVBlankRate(int rate)
{
    m_VBRate = rate;
    if (m_bInitialized) {
        GLContext* pContext = m_pWindows[0]->getGLContext();
        pContext->activate();
        bool bOK = pContext->initVBlank(rate);
        m_Framerate = Display::get()->getRefreshRate()/m_VBRate;
        if (!bOK || rate == 0) {
            AVG_LOG_WARNING("Using framerate of " << m_Framerate <<
                    " instead of VBRate of " << m_VBRate);
            m_VBRate = 0;
        }
    }
}

bool DisplayEngine::wasFrameLate()
{
    return m_bFrameLate;
}

void DisplayEngine::setGamma(float red, float green, float blue)
{
    if (red > 0) {
        bool bOk = internalSetGamma(red, green, blue);
        m_Gamma[0] = red;
        m_Gamma[1] = green;
        m_Gamma[2] = blue;
        if (!bOk) {
            AVG_LOG_WARNING("Unable to set display gamma.");
        }
    }
}

void DisplayEngine::setMousePos(const IntPoint& pos)
{
    SDL_WarpMouse(pos.x, pos.y);
}

int DisplayEngine::getKeyModifierState() const
{
    return SDL_GetModState();
}

void DisplayEngine::setWindowTitle(const string& sTitle)
{
    SDL_WM_SetCaption(sTitle.c_str(), 0);
}

unsigned DisplayEngine::getNumWindows() const
{
    return m_pWindows.size();
}

const WindowPtr DisplayEngine::getWindow(unsigned i) const
{
    return m_pWindows[i];
}

SDLWindowPtr DisplayEngine::getSDLWindow() const
{
    return boost::dynamic_pointer_cast<SDLWindow>(m_pWindows[0]);
}

static ProfilingZoneID WaitProfilingZone("Render - wait");

void DisplayEngine::frameWait()
{
    ScopeTimer Timer(WaitProfilingZone);

    m_NumFrames++;

    m_FrameWaitStartTime = TimeSource::get()->getCurrentMicrosecs();
    m_TargetTime = m_LastFrameTime+(long long)(1000000/m_Framerate);
    m_bFrameLate = false;
    if (m_VBRate == 0) {
        if (m_FrameWaitStartTime <= m_TargetTime) {
            long long WaitTime = (m_TargetTime-m_FrameWaitStartTime)/1000;
            if (WaitTime > 5000) {
                AVG_LOG_WARNING("DisplayEngine: waiting " << WaitTime << " ms.");
            }
            TimeSource::get()->sleepUntil(m_TargetTime/1000);
        }
    }
}

void DisplayEngine::swapBuffers()
{
    for (unsigned i=0; i<m_pWindows.size(); ++i) {
        m_pWindows[i]->swapBuffers();
    }
}

void DisplayEngine::checkJitter()
{
    if (m_LastFrameTime == 0) {
        m_EffFramerate = 0;
    } else {
        long long curIntervalTime = TimeSource::get()->getCurrentMicrosecs()
                -m_LastFrameTime;
        m_EffFramerate = 1000000.0f/curIntervalTime;
    }

    long long frameTime = TimeSource::get()->getCurrentMicrosecs();
    int maxDelay;
    if (m_VBRate == 0) {
        maxDelay = 2;
    } else {
        maxDelay = 6;
    }
    if ((frameTime - m_TargetTime)/1000 > maxDelay || m_bFrameLate) {
        m_bFrameLate = true;
        m_FramesTooLate++;
    }

    m_LastFrameTime = frameTime;
    m_TimeSpentWaiting += m_LastFrameTime-m_FrameWaitStartTime;
//    cerr << m_LastFrameTime << ", m_FrameWaitStartTime=" << m_FrameWaitStartTime << endl;
//    cerr << m_TimeSpentWaiting << endl;
}

long long DisplayEngine::getDisplayTime()
{
    return (m_LastFrameTime-m_StartTime)/1000;
}

const IntPoint& DisplayEngine::getSize() const
{
    return m_Size;
}

IntPoint DisplayEngine::getWindowSize() const
{
    if (m_pWindows.empty()) {
        return IntPoint(0,0);
    } else {
        return m_pWindows[0]->getSize();
    }
}

bool DisplayEngine::isFullscreen() const
{
    AVG_ASSERT(!m_pWindows.empty());
    return m_pWindows[0]->isFullscreen();
}

void DisplayEngine::showCursor(bool bShow)
{
#ifdef _WIN32
#define MAX_CORE_POINTERS   6
    // Hack to fix a pointer issue with fullscreen, SDL and touchscreens
    // Refer to Mantis bug #140
    for (int i = 0; i < MAX_CORE_POINTERS; ++i) {
        ShowCursor(bShow);
    }
#else
    if (bShow) {
        SDL_ShowCursor(SDL_ENABLE);
    } else {
        SDL_ShowCursor(SDL_DISABLE);
    }
#endif
}

BitmapPtr DisplayEngine::screenshot(int buffer)
{
    IntRect destRect;
    for (unsigned i=0; i != m_pWindows.size(); ++i) {
        IntRect winDims(m_pWindows[i]->getPos(),
                m_pWindows[i]->getPos()+m_pWindows[i]->getSize());
        destRect.expand(winDims);
    }

    BitmapPtr pDestBmp = BitmapPtr(new Bitmap(destRect.size(),
            BitmapLoader::get()->getDefaultPixelFormat(false)));
    for (unsigned i=0; i != m_pWindows.size(); ++i) {
        BitmapPtr pWinBmp = m_pWindows[i]->screenshot(buffer);
        IntPoint pos = m_pWindows[i]->getPos() - destRect.tl;
        pDestBmp->blt(*pWinBmp, pos);
    }
    return pDestBmp;
}

vector<EventPtr> DisplayEngine::pollEvents()
{
    vector<EventPtr> pEvents;
    for (unsigned i=0; i != m_pWindows.size(); ++i) {
        vector<EventPtr> pWinEvents =  m_pWindows[i]->pollEvents();
        pEvents.insert(pEvents.end(), pWinEvents.begin(), pWinEvents.end());
    }
    return pEvents;
}

bool DisplayEngine::internalSetGamma(float red, float green, float blue)
{
#ifdef __APPLE__
    // Workaround for broken SDL_SetGamma for libSDL 1.2.15 under Lion
    CGError err = CGSetDisplayTransferByFormula(kCGDirectMainDisplay, 0, 1, 1/red,
            0, 1, 1/green, 0, 1, 1/blue);
    return (err == CGDisplayNoErr);
#else
    int err = SDL_SetGamma(float(red), float(green), float(blue));
    return (err != -1);
#endif
}

}
<|endoftext|>


<commit_before>
#include "afgreader/src/reader.h"
#include "graph/edges_set.cpp"
#include <cstring>
#include <fstream>
#include <iostream>
#include <memory>
#include <string>

using std::shared_ptr;
using std::string;
using AMOS::Overlap;
using AMOS::Read;
using AMOS::Reader;
using Graph::EdgesSet;

const double EPSILON = 0.15;
const double ALPHA = 3;

bool compare_edges(const pair<int, shared_ptr<Overlap>>& lhs, const pair<int, shared_ptr<Overlap>>& rhs) {
  return lhs.first < rhs.first;
}

inline bool eq(double x, double y, double eps) {
  return y <= x + eps && x <= y + eps;
}

// tests if o1 is transitive edge considering o2 and o3.
bool is_transitive(const Overlap& o1, const Overlap& o2, const Overlap& o3) {
  auto A = o1.a_id;
  auto B = o1.b_id;
  auto C = o2.a_id;
  if (C == A) {
    C = o2.b_id;
  }
  if (o2.use_suffix(C) == o3.use_suffix(C)) {
    return false;
  }
  if (o1.use_suffix(A) != o2.use_suffix(A)) {
    return false;
  }
  if (o1.use_suffix(B) != o3.use_suffix(B)) {
    return false;
  }
  if (!eq(
        o2.hanging_length(A) + o3.hanging_length(C),
        o1.hanging_length(A),
        EPSILON * o1.length() + ALPHA)) {
    return false;
  }
  if (!eq(
        o2.hanging_length(C) + o3.hanging_length(B),
        o1.hanging_length(B),
        EPSILON * o1.length() + ALPHA)) {
    return false;
  }
  return true;
}

int get_non_transitives(vector<shared_ptr<Overlap>>* dst_container, vector<shared_ptr<Overlap>>& edges_list) {
  int valid = 0;

  // create that data structure to allow fast access to all edges coincident
  // with particular node.
  EdgesSet<shared_ptr<Overlap>> edges_set;
  for (const auto& edge : edges_list) {
    edges_set.add(edge->a_id, edge->b_id, edge);
    edges_set.add(edge->b_id, edge->a_id, edge);
  }

  // sort so we can reduce complexity on iterating edges.
  for (auto unsorted : edges_set) {
    unsorted.second.sort();
  }

  // we are iterating all (x, y), (x, a), (y, a) in hope that we will find that
  // (x,y) is transitive edge when considering (x, a) and (y, a).
  // x -> y, x -> a -> y; x -> y can be information overhead.
  for (const auto& overlap : edges_list) {
    auto& src = overlap->a_id;
    auto& dst = overlap->b_id;

    auto& v1 = edges_set[src], v2 = edges_set[dst];
    auto it1 = v1.begin(), it2 = v2.begin();

    bool transitive = false;
    while (!transitive && it1 != v1.end() && it2 != v2.end()) {
      if (it1->first == overlap->a_id || it1->first == overlap->b_id) {
        ++it1;
        continue;
      }
      if (it2->first == overlap->a_id || it2->first == overlap->b_id) {
        ++it2;
        continue;
      }
      if (it1->first == it2->first) {
        if (is_transitive(*overlap, *it1->second, *it2->second)) {
          transitive = true;
        }
        ++it1;
        ++it2;
      } else if (it1->first < it2->first) {
        ++it1;
      } else {
        ++it2;
      }
    }

    if (!transitive) {
      dst_container->emplace_back(overlap);
    }
  }

  return valid;
}

void fill_reads(vector<shared_ptr<Overlap>>& overlaps, map<uint32_t, shared_ptr<Read>>& reads) {
  for (auto o : overlaps) {
    o->a = reads[o->a_id];
    o->b = reads[o->b_id];
  }
}

int read_from_stream(istream& input, map<uint32_t, shared_ptr<Read>>& reads, vector<shared_ptr<Overlap>>& edges) {
  Reader reader(input);

  int stored = 0;
  while (reader.has_next()) {
    if (reader.next_type() == AMOS::OVERLAP) {
      Overlap* overlap = new Overlap();
      if (!reader.next(overlap)) {
        cerr << "Error while reading overlap" << endl;
        continue;
      }

      edges.emplace_back(shared_ptr<Overlap>(overlap));
      stored++;
    } else if (reader.next_type() == AMOS::READ) {
      Read *read = new Read();
      if (!reader.next(read)) {
        cerr << "Error while reading overlap" << endl;
        continue;
      }

      reads[read->iid] = shared_ptr<Read>(read);
      stored++;
    } else {
      reader.skip_next();
      continue;
    }
  }

  return stored;
}

int main(int argc, char **argv) {
  vector<string> input_streams;

  for (int i = 1; i < argc; ++i) {
    input_streams.emplace_back(argv[i]);
  }
  if (argc == 2) {
    input_streams.emplace_back("-");
  }

  vector<shared_ptr<Overlap>> overlaps;
  map<uint32_t, shared_ptr<Read>> reads;

  for (auto stream_name : input_streams) {
    cerr << "Starting reading from " << stream_name << endl;
    if (stream_name == "-") {
      read_from_stream(cin, reads, overlaps);
    } else {
      fstream file(stream_name);
      read_from_stream(file, reads, overlaps);
      file.close();
    }
    cerr << "Finished reading from " << stream_name << endl;
  }

  cerr << "Read " << overlaps.size() << " reads" << endl;
  cerr << "Read " << reads.size() << " overlaps" << endl;

  fill_reads(overlaps, reads);

  vector<shared_ptr<Overlap>> non_transitive_edges;
  get_non_transitives(&non_transitive_edges, overlaps);

  cerr << "Filtered " << (overlaps.size() - non_transitive_edges.size()) << " overlaps" << endl;
}
<commit_msg>[filter-transitive]: add counter to input logging<commit_after>
#include "afgreader/src/reader.h"
#include "graph/edges_set.cpp"
#include <cstring>
#include <fstream>
#include <iostream>
#include <memory>
#include <string>

using std::shared_ptr;
using std::string;
using AMOS::Overlap;
using AMOS::Read;
using AMOS::Reader;
using Graph::EdgesSet;

const double EPSILON = 0.15;
const double ALPHA = 3;

bool compare_edges(const pair<int, shared_ptr<Overlap>>& lhs, const pair<int, shared_ptr<Overlap>>& rhs) {
  return lhs.first < rhs.first;
}

inline bool eq(double x, double y, double eps) {
  return y <= x + eps && x <= y + eps;
}

// tests if o1 is transitive edge considering o2 and o3.
bool is_transitive(const Overlap& o1, const Overlap& o2, const Overlap& o3) {
  auto A = o1.a_id;
  auto B = o1.b_id;
  auto C = o2.a_id;
  if (C == A) {
    C = o2.b_id;
  }
  if (o2.use_suffix(C) == o3.use_suffix(C)) {
    return false;
  }
  if (o1.use_suffix(A) != o2.use_suffix(A)) {
    return false;
  }
  if (o1.use_suffix(B) != o3.use_suffix(B)) {
    return false;
  }
  if (!eq(
        o2.hanging_length(A) + o3.hanging_length(C),
        o1.hanging_length(A),
        EPSILON * o1.length() + ALPHA)) {
    return false;
  }
  if (!eq(
        o2.hanging_length(C) + o3.hanging_length(B),
        o1.hanging_length(B),
        EPSILON * o1.length() + ALPHA)) {
    return false;
  }
  return true;
}

int get_non_transitives(vector<shared_ptr<Overlap>>* dst_container, vector<shared_ptr<Overlap>>& edges_list) {
  int valid = 0;

  // create that data structure to allow fast access to all edges coincident
  // with particular node.
  EdgesSet<shared_ptr<Overlap>> edges_set;
  for (const auto& edge : edges_list) {
    edges_set.add(edge->a_id, edge->b_id, edge);
    edges_set.add(edge->b_id, edge->a_id, edge);
  }

  // sort so we can reduce complexity on iterating edges.
  for (auto unsorted : edges_set) {
    unsorted.second.sort();
  }

  // we are iterating all (x, y), (x, a), (y, a) in hope that we will find that
  // (x,y) is transitive edge when considering (x, a) and (y, a).
  // x -> y, x -> a -> y; x -> y can be information overhead.
  for (const auto& overlap : edges_list) {
    auto& src = overlap->a_id;
    auto& dst = overlap->b_id;

    auto& v1 = edges_set[src], v2 = edges_set[dst];
    auto it1 = v1.begin(), it2 = v2.begin();

    bool transitive = false;
    while (!transitive && it1 != v1.end() && it2 != v2.end()) {
      if (it1->first == overlap->a_id || it1->first == overlap->b_id) {
        ++it1;
        continue;
      }
      if (it2->first == overlap->a_id || it2->first == overlap->b_id) {
        ++it2;
        continue;
      }
      if (it1->first == it2->first) {
        if (is_transitive(*overlap, *it1->second, *it2->second)) {
          transitive = true;
        }
        ++it1;
        ++it2;
      } else if (it1->first < it2->first) {
        ++it1;
      } else {
        ++it2;
      }
    }

    if (!transitive) {
      dst_container->emplace_back(overlap);
    }
  }

  return valid;
}

void fill_reads(vector<shared_ptr<Overlap>>& overlaps, map<uint32_t, shared_ptr<Read>>& reads) {
  for (auto o : overlaps) {
    o->a = reads[o->a_id];
    o->b = reads[o->b_id];
  }
}

int read_from_stream(istream& input, map<uint32_t, shared_ptr<Read>>& reads, vector<shared_ptr<Overlap>>& edges) {
  Reader reader(input);

  int stored = 0;
  while (reader.has_next()) {
    if (reader.next_type() == AMOS::OVERLAP) {
      Overlap* overlap = new Overlap();
      if (!reader.next(overlap)) {
        cerr << "Error while reading overlap" << endl;
        continue;
      }

      edges.emplace_back(shared_ptr<Overlap>(overlap));
      stored++;
    } else if (reader.next_type() == AMOS::READ) {
      Read *read = new Read();
      if (!reader.next(read)) {
        cerr << "Error while reading overlap" << endl;
        continue;
      }

      reads[read->iid] = shared_ptr<Read>(read);
      stored++;
    } else {
      reader.skip_next();
      continue;
    }
  }

  return stored;
}

int main(int argc, char **argv) {
  vector<string> input_streams;

  for (int i = 1; i < argc; ++i) {
    input_streams.emplace_back(argv[i]);
  }
  if (argc == 2) {
    input_streams.emplace_back("-");
  }

  vector<shared_ptr<Overlap>> overlaps;
  map<uint32_t, shared_ptr<Read>> reads;

  for (auto stream_name : input_streams) {
    cerr << "Starting reading from " << stream_name << endl;
    int read = 0;
    if (stream_name == "-") {
      read = read_from_stream(cin, reads, overlaps);
    } else {
      fstream file(stream_name);
      read = read_from_stream(file, reads, overlaps);
      file.close();
    }
    cerr << "Read " << read << " objects from " << stream_name << endl;
  }

  cerr << "Read " << overlaps.size() << " reads" << endl;
  cerr << "Read " << reads.size() << " overlaps" << endl;

  fill_reads(overlaps, reads);

  vector<shared_ptr<Overlap>> non_transitive_edges;
  get_non_transitives(&non_transitive_edges, overlaps);

  cerr << "Filtered " << (overlaps.size() - non_transitive_edges.size()) << " overlaps" << endl;
}
<|endoftext|>