<commit_before>// Gao Wang and Kushal K. Dey (c) 2016
// code format configuration: clang-format -style=Google -dump-config >
// ~/.clang-format
#include "pfa.hpp"
#include <cstdio>
#include <ctime>
#include <fstream>
#include <iostream>

//! EM algorithm for paired factor analysis
// @param X [N, J] observed data matrix
// @param F [K, J] initial factor matrix
// @param P [K, K] initial frequency matrix of factor pairs, an upper diagonal
// matrix
// @param q [C, 1] initial vector of possible membership loadings, a discrete
// set
// @param N [int_pt] number of rows of matrix X
// @param J [int_pt] number of columns of matrix X and F
// @param K [int_pt] number of rows of matrix F and P
// @param C [int_pt] number of elements in q
// @param alpha0 [double_pt] Dirichlet prior for factor weights
// @param beta0 [double_pt] Dirichlet prior for grid weights
// @param tol [double_pt] tolerance for convergence
// @param maxiter [int_pt] maximum number of iterations
// @param niter [int_pt] number of iterations
// @param loglik [maxiter, 1] log likelihood, track of convergence (return)
// @param L [N, K] Loading matrix (return)
// @param alpha [K, K] Dirichlet posterior parameter matrix for factor pair
// weights (return)
// @param beta [C, 1] Dirichlet posterior parameter vector for grid weights
// (return)
// @param status [int_pt] return status, 0 for good, 1 for error (return)
// @param logfn_1 [int_pt] log file 1 name as integer converted from character
// array
// @param nlf_1 [int_pt] length of above
// @param logfn_2 [int_pt] log file 2 name as integer converted from character
// array
// @param nlf_2 [int_pt] length of above
// @param n_threads [int_pt] number of threads for parallel processing

int pfa_em(double* X, double* F, double* P, double* q, int* N, int* J, int* K,
           int* C, double* alpha0, double* beta0, double* tol, int* maxiter,
           int* niter, double* loglik, double* L, double* alpha, double* beta,
           int* status, int* logfn_1, int* nlf_1, int* logfn_2, int* nlf_2,
           int* n_threads) {
  //
  // Set up logfiles
  //
  std::fstream f1;
  std::fstream f2;
  if (*nlf_1 > 0) {
    char f1_log[(*nlf_1) + 1];
    char f2_log[(*nlf_2) + 1];
    for (int i = 0; i < *nlf_1; i++) f1_log[i] = (char)*(logfn_1 + i);
    for (int i = 0; i < *nlf_2; i++) f2_log[i] = (char)*(logfn_2 + i);
    f1_log[*nlf_1] = '\0';
    f2_log[*nlf_2] = '\0';
    // log file
    f1.open(f1_log, std::fstream::out);
    time_t now;
    time(&now);
    f1 << "#\n# " << asctime(localtime(&now)) << "#\n\n";
    f1.close();
    f1.open(f1_log, std::fstream::app);
    // debug file
    if (*nlf_2 > 0) {
      f2.open(f2_log, std::fstream::out);
      f2 << "#\n# " << asctime(localtime(&now)) << "#\n\n";
      f2.close();
      f2.open(f2_log, std::fstream::app);
    }
  }
  //
  // Fit model
  //
  *niter = 0;
  PFA_EM model(X, F, P, q, L, *N, *J, *K, *C);
  model.set_threads(*n_threads);
  model.write(f1, 0);
  while (*niter <= *maxiter) {
    if (f1.is_open()) {
      f1 << "#----------------------------------\n";
      f1 << "# Iteration " << *niter << "\n";
      f1 << "#----------------------------------\n";
      model.write(f1, 1);
      if (f2.is_open()) {
        f2 << "#----------------------------------\n";
        f2 << "# Iteration " << *niter << "\n";
        f2 << "#----------------------------------\n";
        model.write(f2, 2);
      }
    }
    int e_status = model.E_step();
    if (e_status != 0) {
      std::cerr << "[ERROR] E step failed!" << std::endl;
      *status = 1;
      break;
    }
    loglik[*niter] = model.get_loglik();
    if (loglik[*niter] != loglik[*niter]) {
      std::cerr << "[ERROR] likelihood nan produced!" << std::endl;
      *status = 1;
      break;
    }
    if (f1.is_open()) {
      f1 << "Loglik:\n" << loglik[*niter] << "\n";
    }
    (*niter)++;
    // check convergence
    if (*niter > 1) {
      double diff = loglik[(*niter) - 1] - loglik[(*niter) - 2];
      // check monotonicity
      if (diff < 0.0) {
        std::cerr << "[ERROR] likelihood decreased in EM algorithm!"
                  << std::endl;
        *status = 1;
        break;
      }
      // converged
      if (diff < *tol) break;
    }
    if (*niter == *maxiter) {
      // did not converge
      *status = 1;
      break;
    }
    // continue with more iterations
    model.M_step();
  }
  if (*status)
    std::cerr << "[WARNING] PFA failed to converge after " << *niter
              << " iterations!" << std::endl;
  if (f1.is_open()) f1.close();
  if (f2.is_open()) f2.close();
  return 0;
}

// this computes log delta
// return: k1k2 by q by N tensor of log delta
void PFA_EM::update_ldelta() {
#pragma omp parallel for num_threads(n_threads)
  for (size_t k1 = 0; k1 < F.n_rows; k1++) {
    for (size_t k2 = 0; k2 <= k1; k2++) {
      // given k1, k2 and q, density is a N-vector
      for (size_t qq = 0; qq < q.n_elem; qq++) {
        if ((k1 != k2) | (k1 == k2 & qq == 0)) {
          arma::vec Dn_delta = arma::zeros<arma::vec>(D.n_rows);
          for (size_t j = 0; j < D.n_cols; j++) {
            arma::vec density = D.col(j);
            double m =
                (k2 < k1)
                    ? q.at(qq) * F.at(k2, j) + (1 - q.at(qq)) * F.at(k1, j)
                    : F.at(k1, j);
            Dn_delta += density.transform(
                [=](double x) { return (normal_pdf_log(x, m, s.at(j))); });
          }
          Dn_delta += std::log(P.at(k1, k2));
          // FIXME: this is slow, due to the cube/slice structure
          for (size_t n = 0; n < D.n_rows; n++)
            delta.slice(n).at(F_pair_coord[std::make_pair(k1, k2)], qq) = Dn_delta.at(n);
        }
      }
    }
  }
}

// this computes loglik and delta
// this results in a N by k1k2 matrix of loglik
// and the delta tensor on its original (exp) scale, with each slice summing to one
void PFA_EM::update_loglik_and_delta() {
  arma::vec loglik_vec;
  loglik_vec.set_size(D.n_rows);
#pragma omp parallel for num_threads(n_threads)
  for (size_t qq = 0; qq < q.n_elem; qq++) {
    // 1. for each N by k1k2 matrix slice from the log of sum of
  }
  for (size_t n = 0; n < D.n_rows; n++) {
    // 1. find the log of sum of exp(delta.slice(n))
    // 2. exp transform delta to its proper scale: set delta prop to exp(delta)
    // 3. scale delta.slice(n) to sum to 1
    // a numeric trick is used to calculate log(sum(exp(x)))
    // lsum=function(lx){
    //  m = max(lx)
    //  m + log(sum(exp(lx-m)))
    // }
    // see gaow/pfar/issue/2 for a discussion
    double delta_n_max = delta.slice(n).max();
    delta.slice(n) = arma::exp(delta.slice(n) - delta_n_max);
    for (size_t k = 0; k < F.n_rows; k++) {
      // reset single factor case: has to be zero for all but the first grid
      double tmp = delta.slice(n).at(F_pair_coord[std::make_pair(k, k)], 0);
      delta.slice(n).row(F_pair_coord[std::make_pair(k, k)]).fill(0);
      delta.slice(n).at(F_pair_coord[std::make_pair(k, k)], 0) = tmp;
    }
    double sum_delta_n = arma::accu(delta.slice(n));
    loglik_vec.at(n) = std::log(sum_delta_n) + delta_n_max;
    delta.slice(n) = delta.slice(n) / sum_delta_n;
  }
  loglik = arma::accu(loglik_vec);
}

// update factor pair weights
void PFA_EM::update_paired_factor_weights() {
  arma::vec pik1k2 = arma::vectorise(arma::mean(arma::sum(delta, 1), 2));
#pragma omp parallel for num_threads(n_threads)
  for (size_t k1 = 0; k1 < P.n_rows; k1++) {
    for (size_t k2 = 0; k2 <= k1; k2++) {
      P.at(k1, k2) = pik1k2.at(F_pair_coord[std::make_pair(k1, k2)]);
    }
  }
}

void PFA_EM::update_factor_model() {
  // Factors F and loadings L are to be updated here
  // Need to compute 2 matrices in order to solve F
  L.fill(0);
  arma::mat L2 = L;
#pragma omp parallel for num_threads(n_threads) collapse(2)
  for (size_t k = 0; k < F.n_rows; k++) {
    // I. Compute the k-th column for E(L), the N X K matrix:
    // and II. the diagonal elements for E(W), the K X K matrix
    for (size_t i = 0; i < F.n_rows; i++) {
#pragma omp critical
      {
        if (k < i) {
          // I.
          L.col(k) += delta.col(F_pair_coord[std::make_pair(k, i)]) * avg_q;
          // II.
          L2.col(k) += delta.col(F_pair_coord[std::make_pair(k, i)]) * avg_q2;
        }
        if (k > i) {
          L.col(k) += delta.col(F_pair_coord[std::make_pair(k, i)]) * avg_1q;
          L2.col(k) += delta.col(F_pair_coord[std::make_pair(k, i)]) * avg_1q2;
        }
        if (k == i) {
          L.col(k) += delta.col(F_pair_coord[std::make_pair(k, i)]);
          L2.col(k) += delta.col(F_pair_coord[std::make_pair(k, i)]);
        }
      }
    }
  }
  // II. diagonal elements for E(W)
  W.diag() = arma::sum(L2);
// III. Compute off-diagonal elements for E(W), the K X K matrix
#pragma omp parallel for num_threads(n_threads)
  for (size_t k1 = 0; k1 < F.n_rows; k1++) {
    for (size_t k2 = 0; k2 < k1; k2++) {
      W.at(k1, k2) =
          arma::sum(delta.col(F_pair_coord[std::make_pair(k1, k2)]) * avg_q1q);
      W.at(k2, k1) = W.at(k1, k2);
    }
  }
  // IV. Solve F
  F = arma::solve(W, L.t() * D);
}

// S is the residual standard error vector to be updated for each feature
void PFA_EM::update_residual_error() {
#pragma omp parallel for num_threads(n_threads)
  for (size_t j = 0; j < D.n_cols; j++) {
    s.at(j) = 0;
    for (size_t k1 = 0; k1 < F.n_rows; k1++) {
      for (size_t k2 = 0; k2 <= k1; k2++) {
        if (k2 < k1) {
          arma::vec tmp = arma::zeros<arma::vec>(D.n_rows);
          for (size_t qq = 0; qq < q.n_elem; qq++) {
            tmp += arma::pow(D.col(j) - q.at(qq) * F.at(k2, j) -
                                 (1 - q.at(qq)) * F.at(k1, j),
                             2);
          }
          s.at(j) +=
              arma::accu(delta.col(F_pair_coord[std::make_pair(k1, k2)]) /
                         double(q.n_elem) % tmp);
        } else {
          s.at(j) +=
              arma::accu(delta.col(F_pair_coord[std::make_pair(k1, k2)]) %
                         arma::pow(D.col(j) - F.at(k1, j), 2));
        }
      }
    }
    s.at(j) = std::sqrt(s.at(j) / double(D.n_rows));
  }
}
<commit_msg>Finishing up the previous patch<commit_after>// Gao Wang and Kushal K. Dey (c) 2016
// code format configuration: clang-format -style=Google -dump-config >
// ~/.clang-format
#include "pfa.hpp"
#include <cstdio>
#include <ctime>
#include <fstream>
#include <iostream>

//! EM algorithm for paired factor analysis
// @param X [N, J] observed data matrix
// @param F [K, J] initial factor matrix
// @param P [K, K] initial frequency matrix of factor pairs, an upper diagonal
// matrix
// @param q [C, 1] initial vector of possible membership loadings, a discrete
// set
// @param N [int_pt] number of rows of matrix X
// @param J [int_pt] number of columns of matrix X and F
// @param K [int_pt] number of rows of matrix F and P
// @param C [int_pt] number of elements in q
// @param alpha0 [double_pt] Dirichlet prior for factor weights
// @param beta0 [double_pt] Dirichlet prior for grid weights
// @param tol [double_pt] tolerance for convergence
// @param maxiter [int_pt] maximum number of iterations
// @param niter [int_pt] number of iterations
// @param loglik [maxiter, 1] log likelihood, track of convergence (return)
// @param L [N, K] Loading matrix (return)
// @param alpha [K, K] Dirichlet posterior parameter matrix for factor pair
// weights (return)
// @param beta [C, 1] Dirichlet posterior parameter vector for grid weights
// (return)
// @param status [int_pt] return status, 0 for good, 1 for error (return)
// @param logfn_1 [int_pt] log file 1 name as integer converted from character
// array
// @param nlf_1 [int_pt] length of above
// @param logfn_2 [int_pt] log file 2 name as integer converted from character
// array
// @param nlf_2 [int_pt] length of above
// @param n_threads [int_pt] number of threads for parallel processing

int pfa_em(double* X, double* F, double* P, double* q, int* N, int* J, int* K,
           int* C, double* alpha0, double* beta0, double* tol, int* maxiter,
           int* niter, double* loglik, double* L, double* alpha, double* beta,
           int* status, int* logfn_1, int* nlf_1, int* logfn_2, int* nlf_2,
           int* n_threads) {
  //
  // Set up logfiles
  //
  std::fstream f1;
  std::fstream f2;
  if (*nlf_1 > 0) {
    char f1_log[(*nlf_1) + 1];
    char f2_log[(*nlf_2) + 1];
    for (int i = 0; i < *nlf_1; i++) f1_log[i] = (char)*(logfn_1 + i);
    for (int i = 0; i < *nlf_2; i++) f2_log[i] = (char)*(logfn_2 + i);
    f1_log[*nlf_1] = '\0';
    f2_log[*nlf_2] = '\0';
    // log file
    f1.open(f1_log, std::fstream::out);
    time_t now;
    time(&now);
    f1 << "#\n# " << asctime(localtime(&now)) << "#\n\n";
    f1.close();
    f1.open(f1_log, std::fstream::app);
    // debug file
    if (*nlf_2 > 0) {
      f2.open(f2_log, std::fstream::out);
      f2 << "#\n# " << asctime(localtime(&now)) << "#\n\n";
      f2.close();
      f2.open(f2_log, std::fstream::app);
    }
  }
  //
  // Fit model
  //
  *niter = 0;
  PFA_EM model(X, F, P, q, L, *N, *J, *K, *C);
  model.set_threads(*n_threads);
  model.write(f1, 0);
  while (*niter <= *maxiter) {
    if (f1.is_open()) {
      f1 << "#----------------------------------\n";
      f1 << "# Iteration " << *niter << "\n";
      f1 << "#----------------------------------\n";
      model.write(f1, 1);
      if (f2.is_open()) {
        f2 << "#----------------------------------\n";
        f2 << "# Iteration " << *niter << "\n";
        f2 << "#----------------------------------\n";
        model.write(f2, 2);
      }
    }
    int e_status = model.E_step();
    if (e_status != 0) {
      std::cerr << "[ERROR] E step failed!" << std::endl;
      *status = 1;
      break;
    }
    loglik[*niter] = model.get_loglik();
    if (loglik[*niter] != loglik[*niter]) {
      std::cerr << "[ERROR] likelihood nan produced!" << std::endl;
      *status = 1;
      break;
    }
    if (f1.is_open()) {
      f1 << "Loglik:\n" << loglik[*niter] << "\n";
    }
    (*niter)++;
    // check convergence
    if (*niter > 1) {
      double diff = loglik[(*niter) - 1] - loglik[(*niter) - 2];
      // check monotonicity
      if (diff < 0.0) {
        std::cerr << "[ERROR] likelihood decreased in EM algorithm!"
                  << std::endl;
        *status = 1;
        break;
      }
      // converged
      if (diff < *tol) break;
    }
    if (*niter == *maxiter) {
      // did not converge
      *status = 1;
      break;
    }
    // continue with more iterations
    model.M_step();
  }
  if (*status)
    std::cerr << "[WARNING] PFA failed to converge after " << *niter
              << " iterations!" << std::endl;
  if (f1.is_open()) f1.close();
  if (f2.is_open()) f2.close();
  return 0;
}

// this computes log delta
// return: k1k2 by q by N tensor of log delta
void PFA_EM::update_ldelta() {
#pragma omp parallel for num_threads(n_threads)
  for (size_t k1 = 0; k1 < F.n_rows; k1++) {
    for (size_t k2 = 0; k2 <= k1; k2++) {
      // given k1, k2 and q, density is a N-vector
      for (size_t qq = 0; qq < q.n_elem; qq++) {
        if ((k1 != k2) | (k1 == k2 & qq == 0)) {
          arma::vec Dn_delta = arma::zeros<arma::vec>(D.n_rows);
          for (size_t j = 0; j < D.n_cols; j++) {
            arma::vec density = D.col(j);
            double m =
                (k2 < k1)
                    ? q.at(qq) * F.at(k2, j) + (1 - q.at(qq)) * F.at(k1, j)
                    : F.at(k1, j);
            Dn_delta += density.transform(
                [=](double x) { return (normal_pdf_log(x, m, s.at(j))); });
          }
          Dn_delta += std::log(P.at(k1, k2));
          // FIXME: this is slow, due to the cube/slice structure
          for (size_t n = 0; n < D.n_rows; n++)
            delta.slice(n).at(F_pair_coord[std::make_pair(k1, k2)], qq) =
                Dn_delta.at(n);
        }
      }
    }
  }
}

// this computes loglik and delta
// this results in a N by k1k2 matrix of loglik
// and the delta tensor on its original (exp) scale, with each slice summing to
// one
void PFA_EM::update_loglik_and_delta() {
  arma::vec loglik_vec;
  loglik_vec.set_size(D.n_rows);
#pragma omp parallel for num_threads(n_threads)
  for (size_t n = 0; n < D.n_rows; n++) {
    // 1. find the log of sum of exp(delta.slice(n))
    // 2. exp transform delta to its proper scale: set delta prop to exp(delta)
    // 3. scale delta.slice(n) to sum to 1
    // a numeric trick is used to calculate log(sum(exp(x)))
    // lsum=function(lx){
    //  m = max(lx)
    //  m + log(sum(exp(lx-m)))
    // }
    // see gaow/pfar/issue/2 for a discussion
    double delta_n_max = delta.slice(n).max();
    delta.slice(n) = arma::exp(delta.slice(n) - delta_n_max);
    for (size_t k = 0; k < F.n_rows; k++) {
      // reset single factor case: has to be zero for all but the first grid
      double tmp = delta.slice(n).at(F_pair_coord[std::make_pair(k, k)], 0);
      delta.slice(n).row(F_pair_coord[std::make_pair(k, k)]).fill(0);
      delta.slice(n).at(F_pair_coord[std::make_pair(k, k)], 0) = tmp;
    }
    double sum_delta_n = arma::accu(delta.slice(n));
    loglik_vec.at(n) = std::log(sum_delta_n) + delta_n_max;
    delta.slice(n) = delta.slice(n) / sum_delta_n;
  }
  loglik = arma::accu(loglik_vec);
}

// update factor pair weights
void PFA_EM::update_paired_factor_weights() {
  arma::vec pik1k2 = arma::vectorise(arma::mean(arma::sum(delta, 1), 2));
#pragma omp parallel for num_threads(n_threads)
  for (size_t k1 = 0; k1 < P.n_rows; k1++) {
    for (size_t k2 = 0; k2 <= k1; k2++) {
      P.at(k1, k2) = pik1k2.at(F_pair_coord[std::make_pair(k1, k2)]);
    }
  }
}

void PFA_EM::update_factor_model() {
  // Factors F and loadings L are to be updated here
  // Need to compute 2 matrices in order to solve F
  L.fill(0);
  arma::mat L2 = L;
#pragma omp parallel for num_threads(n_threads) collapse(2)
  for (size_t k = 0; k < F.n_rows; k++) {
    // I. First we compute the k-th column for E(L), the N X K matrix:
    // generate the proper input for N X Q %*% Q X 1
    // where the N X Q matrix is taken from delta given K1K2
    // and the Q X 1 matrix correspond to the grid of q
    // II. Then we compute the diagonal elements for E(W), the K X K matrix
    // First we still compute a N X K matrix like above but replacing q / 1 - q
    // with q^2 / (1 - q)^2
    // then take colsum to get the K vector as the diagonal
    for (size_t i = 0; i < F.n_rows; i++) {
      // create the LHS Dk1k2, N X Q matrix from delta given k1, k2
      arma::mat Dk1k2(D.n_rows, q.n_elem, arma::fill::zeros);
      for (size_t n = 0; n < D.n_rows; n++) {
        Dk1k2.row(n) = delta.slice(n).row(F_pair_coord[std::make_pair(k, i)]);
      }
#pragma omp critical
      {
        if (k < i) {
          // I.
          L.col(k) += Dk1k2 * q;
          // II.
          L2.col(k) += Dk1k2 * (q % q);
        }
        if (k > i) {
          L.col(k) += Dk1k2 * (1 - q);
          L2.col(k) += Dk1k2 * ((1 - q) % (1 - q));
        }
        if (k == i) {
          L.col(k) += Dk1k2.col(0);
          L2.col(k) += Dk1k2.col(0);
        }
      }
    }
  }
  // II. diagonal elements for E(W)
  W.diag() = arma::sum(L2);
  // III. Compute off-diagonal elements for E(W), the K X K matrix
  // for k1 != k2
  // it involves on the LHS a vector of [q1(1-q1), q2(1-q2) ...]
  // and on the RHS for each pair of (k1, k2) the corresponding row from delta
  // summing over samples
  arma::vec LHS = q % (1 - q);
  arma::mat RHS = arma::sum(delta, 2);
  RHS = RHS.t();
#pragma omp parallel for num_threads(n_threads)
  for (size_t k1 = 0; k1 < F.n_rows; k1++) {
    for (size_t k2 = 0; k2 < k1; k2++) {
      W.at(k1, k2) =
          arma::dot(LHS, RHS.col(F_pair_coord[std::make_pair(k1, k2)]));
      W.at(k2, k1) = W.at(k1, k2);
    }
  }
  // IV. Solve F
  F = arma::solve(W, L.t() * D);
}

// S is the residual standard error vector to be updated for each feature
// FIXME: can this be optimized via transposing the tensor delta?
void PFA_EM::update_residual_error() {
#pragma omp parallel for num_threads(n_threads)
  for (size_t j = 0; j < D.n_cols; j++) {
    s.at(j) = 0;
    for (size_t k1 = 0; k1 < F.n_rows; k1++) {
      for (size_t k2 = 0; k2 <= k1; k2++) {
        for (size_t n = 0; n < D.n_rows; n++) {
          if (k2 < k1) {
            for (size_t qq = 0; qq < q.n_elem; qq++) {
              s.at(j) +=
                  delta.slice(n).at(F_pair_coord[std::make_pair(k1, k2)], qq) *
                  std::pow(D.at(n, j) - q.at(qq) * F.at(k2, j) -
                               (1 - q.at(qq)) * F.at(k1, j),
                           2);
            }
          } else {
            s.at(j) +=
                delta.slice(n).at(F_pair_coord[std::make_pair(k1, k2)], 0) *
                std::pow(D.at(n, j) - F.at(k1, j), 2);
          }
        }
      }
    }
    s.at(j) = std::sqrt(s.at(j) / double(D.n_rows));
  }
}
<|endoftext|>


<commit_before>// Main.cc
// This will start a WDE session.

#include "Renderer.h"

int main()
{
	WDE::Renderer* renderer = new WDE::Renderer(1280, 720);
	renderer->RenderHTML();
	renderer->MainLoop();
	delete renderer;

	return 0;
}
<commit_msg>Changed source filenames to lowercase<commit_after>// main.cc
// This will start a WDE session.

#include "renderer.h"

int main()
{
	WDE::Renderer* renderer = new WDE::Renderer(1280, 720);
	renderer->RenderHTML();
	renderer->MainLoop();
	delete renderer;

	return 0;
}
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2015 - The CM Authors <legal@clickmatcher.com>
 *   All Rights Reserved.
 *
 * This file is CONFIDENTIAL -- Distribution or duplication of this material or
 * the information contained herein is strictly forbidden unless prior written
 * permission is obtained.
 */
#include <stdlib.h>
#include <unistd.h>
#include "fnord/base/random.h"
#include "fnord/net/http/httprouter.h"
#include "fnord/net/http/httpserver.h"
#include "fnord/thread/eventloop.h"
#include "fnord/thread/threadpool.h"
#include "fnord/system/signalhandler.h"
#include "fnord/logging/logoutputstream.h"
#include "customernamespace.h"
#include "tracker/tracker.h"

int main() {
  fnord::system::SignalHandler::ignoreSIGHUP();
  fnord::system::SignalHandler::ignoreSIGPIPE();

  fnord::CatchAndAbortExceptionHandler ehandler;
  ehandler.installGlobalHandlers();

  fnord::log::LogOutputStream logger(fnord::io::OutputStream::getStderr());
  fnord::log::Logger::get()->setMinimumLogLevel(fnord::log::kInfo);
  fnord::log::Logger::get()->listen(&logger);

  auto dwn_ns = new cm::CustomerNamespace();
  dwn_ns->addVHost("dwnapps.net");
  dwn_ns->loadTrackingJS("config/c_dwn/track.js");

  std::unique_ptr<cm::Tracker> tracker(new cm::Tracker());
  tracker->addCustomer(dwn_ns);

  fnord::thread::ThreadPool thread_pool;
  fnord::thread::EventLoop event_loop;

  fnord::http::HTTPRouter http_router;
  http_router.addRouteByPrefixMatch("/", tracker.get());

  fnord::http::HTTPServer http_server(&http_router, &thread_pool);
  http_server.listen(8080);

  for (;;) {
    usleep(10000);
  }

  return 0;
}

<commit_msg>OMerge branch 'master' of /home/paul/tmp/../paulbox/clickmatcher<commit_after>/**
 * Copyright (c) 2015 - The CM Authors <legal@clickmatcher.com>
 *   All Rights Reserved.
 *
 * This file is CONFIDENTIAL -- Distribution or duplication of this material or
 * the information contained herein is strictly forbidden unless prior written
 * permission is obtained.
 */
#include <stdlib.h>
#include <unistd.h>
#include "fnord/base/random.h"
#include "fnord/net/http/httprouter.h"
#include "fnord/net/http/httpserver.h"
#include "fnord/thread/eventloop.h"
#include "fnord/thread/threadpool.h"
#include "fnord/system/signalhandler.h"
#include "fnord/logging/logoutputstream.h"
#include "customernamespace.h"
#include "tracker/tracker.h"

int main() {
  fnord::system::SignalHandler::ignoreSIGHUP();
  fnord::system::SignalHandler::ignoreSIGPIPE();

  fnord::CatchAndAbortExceptionHandler ehandler;
  ehandler.installGlobalHandlers();

  fnord::log::LogOutputStream logger(fnord::io::OutputStream::getStderr());
  fnord::log::Logger::get()->setMinimumLogLevel(fnord::log::kInfo);
  fnord::log::Logger::get()->listen(&logger);

  auto dwn_ns = new cm::CustomerNamespace();
  dwn_ns->addVHost("dwnapps.net");
  dwn_ns->loadTrackingJS("config/c_dwn/track.js");

  std::unique_ptr<cm::Tracker> tracker(new cm::Tracker());
  tracker->addCustomer(dwn_ns);

  fnord::thread::ThreadPool thread_pool;
  fnord::thread::EventLoop event_loop;

  fnord::http::HTTPRouter http_router;
  http_router.addRouteByPrefixMatch("/", tracker.get());

  fnord::http::HTTPServer http_server(&http_router, &event_loop);
  http_server.listen(8080);

  event_loop.run();

  return 0;
}

<|endoftext|>


<commit_before>/* author: @gwzz
 *
 */
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
#include <map>
#include "graph.h"
#include "support.h"
#include "sctfile.h"

using namespace std;

// Pre-define hierarchy array
// CUI: array of top nodes concept id of each hierarchy
// ConName: array of the name of each hierarchy
const long long CUI[19] = {123037004, 404684003, 308916002, 272379006, 363787002, 410607006, 373873005, 78621006, 260787004, 71388002, 362981000, 419891008, 243796009, 900000000000441003, 48176007, 370115009, 123038009, 254291000, 105590001};
const string ConName[19] = {"Body_structure", "Clinical_finding", "Environment_or_geographical_location", "Event", "Observable_entity", "Organism", "Pharmaceutical_biologic_product", "Physical_force", "Physical_object", "Procedure", "Qualifier_value", "Record_artifact", "Situation_with_explicit_context", "SNOMED_CT_Model_Component", "Social_context", "Special_Concept", "Specimen", "Staging_and_scales", "Substance"};

// define global variables
// node_map: store all the concepts [key,value]
// reversed_node_map: store reversed node_map [value,key]
// nodeFile, relationFile, out_put_file, as variable name
string nodeFile = "2016nodes.txt";
string relationFile = "2016relation.txt";

int main(int argc, char* argv[])
{
  if (argc < 2)
  {
    std::cerr << "Usage: " << argv[0] << " SNOMED_CT_FILE_PATH" << std::endl;
    return 1;
  }
  string out_put_folder = "/Users/zhuwei/Desktop/sct_nodes_within_hierarchy/";
  SctFile sf(argv[1]);
  long long top_node;
  std::map<long long, int> node_map;
  std::map<int, long long> reversed_node_map;
  std::vector<long long> output_vector;
  std::string sline;
  std::vector<std::string> relation;
  std::vector<std::string> nodes;

    // Read in node file
  fstream fin;
  fin.open(nodeFile,ios::in);
  while (getline(fin, sline)){
    nodes.push_back(sline);
  }
  fin.close();
  for (int i = 0; i < nodes.size(); ++i){
    node_map[std::stoll(nodes[i])] = i;
  }

  for (map<long long, int>::iterator i = node_map.begin(); i != node_map.end(); ++i)
    reversed_node_map[i->second] = i->first;

  int nodeSize = node_map.size();
  fin.open(relationFile,ios::in);
  while (getline(fin, sline)){
    relation.push_back(sline);
  }
  fin.close();
  // initialize graph g
  Graph g(nodeSize);
  std::vector<long long> is_a_relationship;
  for (auto i : relation){
    is_a_relationship.clear();
    is_a_relationship = Split(i, ',');
    g.addEdge(node_map[is_a_relationship[1]],node_map[is_a_relationship[0]]);
  }

  string out_put_file;
  for (int i = 0; i < 19; ++i){
    output_vector.clear();
    out_put_file.clear();
    out_put_file = out_put_folder + ConName[i];
    top_node = CUI[i];
    output_vector = g.DFS(node_map[top_node]);
    fstream fout;
    fout.open(out_put_file,ios::app);
    for (auto o : output_vector){
        fout << reversed_node_map[o] << endl;
    }
    fout.close();
  }

    return 0;
}<commit_msg>refactor<commit_after>/* author: @gwzz
 *
 */
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
#include <map>
#include "graph.h"
#include "support.h"
#include "sctfile.h"

using namespace std;

// Pre-define hierarchy array
// CUI: array of top nodes concept id of each hierarchy
// ConName: array of the name of each hierarchy
const long long CUI[19] = {123037004, 404684003, 308916002, 272379006, 363787002, 410607006, 373873005, 78621006, 260787004, 71388002, 362981000, 419891008, 243796009, 900000000000441003, 48176007, 370115009, 123038009, 254291000, 105590001};
const string ConName[19] = {"Body_structure", "Clinical_finding", "Environment_or_geographical_location", "Event", "Observable_entity", "Organism", "Pharmaceutical_biologic_product", "Physical_force", "Physical_object", "Procedure", "Qualifier_value", "Record_artifact", "Situation_with_explicit_context", "SNOMED_CT_Model_Component", "Social_context", "Special_Concept", "Specimen", "Staging_and_scales", "Substance"};

// define global variables
// node_map: store all the concepts [key,value]
// reversed_node_map: store reversed node_map [value,key]
// nodeFile, relationFile, out_put_file, as variable name
string nodeFile = "2016nodes.txt";
string relationFile = "2016relation.txt";

int main(int argc, char* argv[])
{
  if (argc < 2)
  {
    std::cerr << "Usage: " << argv[0] << " SNOMED_CT_FILE_PATH" << std::endl;
    return 1;
  }
  string out_put_folder = "/Users/zhuwei/Desktop/sct_nodes_within_hierarchy/";
  SctFile sf(argv[1]);
  long long top_node;
  std::map<long long, int> node_map;
  std::map<int, long long> reversed_node_map;
  std::vector<long long> output_vector;
  std::string sline;
  std::vector<std::string> relation = sf.relations();
  std::vector<std::string> nodes = sf.nodes();

    // Read in node file
  fstream fin;
  // fin.open(nodeFile,ios::in);
  // while (getline(fin, sline)){
  //   nodes.push_back(sline);
  // }
  // fin.close();
  for (int i = 0; i < nodes.size(); ++i){
    node_map[std::stoll(nodes[i])] = i;
  }

  for (map<long long, int>::iterator i = node_map.begin(); i != node_map.end(); ++i)
    reversed_node_map[i->second] = i->first;

  int nodeSize = node_map.size();
  // fin.open(relationFile,ios::in);
  // while (getline(fin, sline)){
  //   relation.push_back(sline);
  // }
  // fin.close();
  // initialize graph g
  Graph g(nodeSize);
  std::vector<long long> is_a_relationship;
  for (auto i : relation){
    is_a_relationship.clear();
    is_a_relationship = Split(i, ',');
    g.addEdge(node_map[is_a_relationship[1]],node_map[is_a_relationship[0]]);
  }

  string out_put_file;
  for (int i = 0; i < 19; ++i){
    output_vector.clear();
    out_put_file.clear();
    out_put_file = out_put_folder + ConName[i];
    top_node = CUI[i];
    output_vector = g.DFS(node_map[top_node]);
    fstream fout;
    fout.open(out_put_file,ios::app);
    for (auto o : output_vector){
        fout << reversed_node_map[o] << endl;
    }
    fout.close();
  }

    return 0;
}<|endoftext|>


<commit_before>#include "zs.hh"

#define REPL_PROMPT ">> "

int main(){
  install_builtin();

  vm.code.push_back(make_cons_list({intern(vm.symtable(), "read-eval-print-loop")}));
  eval();

  return 0;
}
<commit_msg>cleanup<commit_after>#include "zs.hh"

int main(){
  install_builtin();

  vm.code.push_back(make_cons_list({intern(vm.symtable(), "read-eval-print-loop")}));
  eval();

  return 0;
}
<|endoftext|>


<commit_before>#include <fstream>

#include "cpu.h"

int main() {
    using namespace std;

    ifstream rom("../image/rom");
    ifstream flash("../image/disk0");

    CPU cpu(rom, flash);

    cpu.run();

}

<commit_msg>buffer rom and flash into memory<commit_after>#include <fstream>
#include <sstream>

#include "cpu.h"

int main() {
    using namespace std;

    ifstream rom("../image/rom");
    ifstream flash("../image/disk0");

    // copy files to memory to speed up access
    stringstream rom_buffer;
    stringstream flash_buffer;
    copy(istreambuf_iterator<char>(rom), istreambuf_iterator<char>(),
         ostreambuf_iterator<char>(rom_buffer));
    copy(istreambuf_iterator<char>(flash), istreambuf_iterator<char>(),
         ostreambuf_iterator<char>(flash_buffer));

    CPU cpu(rom_buffer, flash_buffer);

    cpu.run();

}

<|endoftext|>


<commit_before>/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2011, Willow Garage, Inc.
 *  All rights reserved.
 *
 *  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 Willow Garage, Inc. 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.
 *
 * $Id$
 *
 */

#include "pcl/impl/instantiate.hpp"
#include "pcl/point_types.h"
#include "pcl/surface/poisson.h"
#include "pcl/surface/impl/poisson.hpp"

// Instantiations of specific point types
PCL_INSTANTIATE(Poisson, (pcl::PointNormal)(pcl::PointXYZRGBNormal)(pcl::PointXYZINormal));

<commit_msg>disabling optimizations for Poisson on Windows - should fix the unit tests<commit_after>/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2011, Willow Garage, Inc.
 *  All rights reserved.
 *
 *  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 Willow Garage, Inc. 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.
 *
 * $Id$
 *
 */

#ifdef WIN32
#pragma optimize("g", off)
#endif WIN32

#include "pcl/impl/instantiate.hpp"
#include "pcl/point_types.h"
#include "pcl/surface/poisson.h"
#include "pcl/surface/impl/poisson.hpp"

// Instantiations of specific point types
PCL_INSTANTIATE(Poisson, (pcl::PointNormal)(pcl::PointXYZRGBNormal)(pcl::PointXYZINormal));

<|endoftext|>


<commit_before>/*********************************************************************
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2008, Willow Garage, Inc.
 *  All rights reserved.
 *
 *  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 Willow Garage 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.
 *********************************************************************/

/*
  Author: Melonee Wise
  Contributors: Dave Coleman, Jonathan Bohren, Bob Holmberg, Wim Meeussen
  Desc: Implements a standard proportional-integral-derivative controller
*/

#include <control_toolbox/pid.h>
#include <tinyxml.h>

namespace control_toolbox {

static const std::string DEFAULT_NAMESPACE = "pid"; // \todo better default prefix?

Pid::Pid(double p, double i, double d, double i_max, double i_min)
  : dynamic_reconfig_initialized_(false)
{
  setGains(p,i,d,i_max,i_min);

  reset();
}

Pid::Pid(const Pid &source)
   : dynamic_reconfig_initialized_(false)
{
  // Copy the realtime buffer to then new PID class
  gains_buffer_ = source.gains_buffer_;

  // Reset the state of this PID controller
  reset();
}

Pid::~Pid()
{
}

void Pid::initPid(double p, double i, double d, double i_max, double i_min,
  const ros::NodeHandle &node)
{
  initPid(p, i, d, i_max, i_min);

  // Create node handle for dynamic reconfigure
  ros::NodeHandle nh(DEFAULT_NAMESPACE);
  initDynamicReconfig(nh);
}

void Pid::initPid(double p, double i, double d, double i_max, double i_min)
{
  setGains(p,i,d,i_max,i_min);

  reset();
}

bool Pid::initParam(const std::string& prefix, const bool quiet)
{
  ros::NodeHandle nh(prefix);
  return init(nh, quiet);
}

bool Pid::init(const ros::NodeHandle &node, const bool quiet)
{
  ros::NodeHandle nh(node);

  Gains gains;

  // Load PID gains from parameter server
  if (!nh.getParam("p", gains.p_gain_))
  {
    if (!quiet) {
      ROS_ERROR("No p gain specified for pid.  Namespace: %s", nh.getNamespace().c_str());
    }
    return false;
  }
  // Only the P gain is required, the I and D gains are optional and default to 0:
  nh.param("i", gains.i_gain_, 0.0);
  nh.param("d", gains.d_gain_, 0.0);

  // Load integral clamp from param server or default to 0
  double i_clamp;
  nh.param("i_clamp", i_clamp, 0.0);
  gains.i_max_ = std::abs(i_clamp);
  gains.i_min_ = -std::abs(i_clamp);
  if(nh.hasParam("i_clamp_min"))
  {
    nh.param("i_clamp_min", gains.i_min_, gains.i_min_); // use i_clamp_min parameter, otherwise keep -i_clamp
    gains.i_min_ = -std::abs(gains.i_min_); // make sure the value is <= 0
  }
  if(nh.hasParam("i_clamp_max"))
  {
    nh.param("i_clamp_max", gains.i_max_, gains.i_max_); // use i_clamp_max parameter, otherwise keep i_clamp
    gains.i_max_ = std::abs(gains.i_max_); // make sure the value is >= 0
  }

  setGains(gains);

  reset();
  initDynamicReconfig(nh);

  return true;
}

bool Pid::initXml(TiXmlElement *config)
{
  // Create node handle for dynamic reconfigure
  ros::NodeHandle nh(DEFAULT_NAMESPACE);

  double i_clamp;
  i_clamp = config->Attribute("iClamp") ? atof(config->Attribute("iClamp")) : 0.0;

  setGains(
    config->Attribute("p") ? atof(config->Attribute("p")) : 0.0,
    config->Attribute("i") ? atof(config->Attribute("i")) : 0.0,
    config->Attribute("d") ? atof(config->Attribute("d")) : 0.0,
    std::abs(i_clamp),
    -std::abs(i_clamp)
  );

  reset();
  initDynamicReconfig(nh);

  return true;
}

void Pid::initDynamicReconfig(ros::NodeHandle &node)
{
  ROS_DEBUG_STREAM_NAMED("pid","Initializing dynamic reconfigure in namespace "
    << node.getNamespace());

  // Start dynamic reconfigure server
  param_reconfig_server_.reset(new DynamicReconfigServer(param_reconfig_mutex_, node));
  dynamic_reconfig_initialized_ = true;

  // Set Dynamic Reconfigure's gains to Pid's values
  updateDynamicReconfig();

  // Set callback
  param_reconfig_callback_ = boost::bind(&Pid::dynamicReconfigCallback, this, _1, _2);
  param_reconfig_server_->setCallback(param_reconfig_callback_);
}

void Pid::reset()
{
  p_error_last_ = 0.0;
  p_error_ = 0.0;
  i_error_ = 0.0;
  d_error_ = 0.0;
  cmd_ = 0.0;
}

void Pid::getGains(double &p, double &i, double &d, double &i_max, double &i_min)
{
  Gains gains = *gains_buffer_.readFromRT();

  p     = gains.p_gain_;
  i     = gains.i_gain_;
  d     = gains.d_gain_;
  i_max = gains.i_max_;
  i_min = gains.i_min_;
}

Pid::Gains Pid::getGains()
{
  return *gains_buffer_.readFromRT();
}

void Pid::setGains(double p, double i, double d, double i_max, double i_min)
{
  Gains gains(p,i,d,i_max,i_min);

  setGains(gains);
}

void Pid::setGains(const Gains &gains)
{
  gains_buffer_.writeFromNonRT(gains);

  // Update dynamic reconfigure with the new gains
  updateDynamicReconfig(gains);
}

void Pid::updateDynamicReconfig()
{
  // Make sure dynamic reconfigure is initialized
  if(!dynamic_reconfig_initialized_)
    return;

  // Get starting values
  control_toolbox::ParametersConfig config;

  // Get starting values
  getGains(config.p, config.i, config.d, config.i_clamp_max, config.i_clamp_min);

  updateDynamicReconfig(config);
}

void Pid::updateDynamicReconfig(Gains gains_config)
{
  // Make sure dynamic reconfigure is initialized
  if(!dynamic_reconfig_initialized_)
    return;

  control_toolbox::ParametersConfig config;

  // Convert to dynamic reconfigure format
  config.p = gains_config.p_gain_;
  config.i = gains_config.i_gain_;
  config.d = gains_config.d_gain_;
  config.i_clamp_max = gains_config.i_max_;
  config.i_clamp_min = gains_config.i_min_;

  updateDynamicReconfig(config);
}

void Pid::updateDynamicReconfig(control_toolbox::ParametersConfig config)
{
  // Make sure dynamic reconfigure is initialized
  if(!dynamic_reconfig_initialized_)
    return;

  // Set starting values, using a shared mutex with dynamic reconfig
  param_reconfig_mutex_.lock();
  param_reconfig_server_->updateConfig(config);
  param_reconfig_mutex_.unlock();
}

void Pid::dynamicReconfigCallback(control_toolbox::ParametersConfig &config, uint32_t level)
{
  ROS_DEBUG_STREAM_NAMED("pid","Dynamics reconfigure callback recieved.");

  // Set the gains
  setGains(config.p, config.i, config.d, config.i_clamp_max, config.i_clamp_min);
}

double Pid::computeCommand(double error, ros::Duration dt)
{
  // Get the gain parameters from the realtime buffer
  Gains gains = *gains_buffer_.readFromRT();

  double p_term, d_term, i_term;
  p_error_ = error; // this is error = target - state

  if (dt == ros::Duration(0.0) || std::isnan(error) || std::isinf(error))
    return 0.0;

  // Calculate proportional contribution to command
  p_term = gains.p_gain_ * p_error_;

  // Calculate the integral of the position error
  i_error_ += dt.toSec() * p_error_;

  // Calculate integral contribution to command
  i_term = gains.i_gain_ * i_error_;

  // Limit i_term so that the limit is meaningful in the output
  i_term = std::max( gains.i_min_, std::min( i_term, gains.i_max_) );

  // Calculate the derivative error
  if (dt.toSec() > 0.0)
  {
    d_error_ = (p_error_ - p_error_last_) / dt.toSec();
    p_error_last_ = p_error_;
  }
  // Calculate derivative contribution to command
  d_term = gains.d_gain_ * d_error_;

  // Compute the command
  cmd_ = p_term + i_term + d_term;

  return cmd_;
}

double Pid::updatePid(double error, ros::Duration dt)
{
  // Get the gain parameters from the realtime buffer
  Gains gains = *gains_buffer_.readFromRT();

  double p_term, d_term, i_term;
  p_error_ = error; //this is pError = pState-pTarget

  if (dt == ros::Duration(0.0) || std::isnan(error) || std::isinf(error))
    return 0.0;

  // Calculate proportional contribution to command
  p_term = gains.p_gain_ * p_error_;

  // Calculate the integral of the position error
  i_error_ += dt.toSec() * p_error_;

  // Calculate integral contribution to command
  i_term = gains.i_gain_ * i_error_;

  // Limit i_term so that the limit is meaningful in the output
  i_term = std::max( gains.i_min_, std::min( i_term, gains.i_max_) );

  // Calculate the derivative error
  if (dt.toSec() > 0.0)
  {
    d_error_ = (p_error_ - p_error_last_) / dt.toSec();
    p_error_last_ = p_error_;
  }
  // Calculate derivative contribution to command
  d_term = gains.d_gain_ * d_error_;

  // Compute the command
  cmd_ = - p_term - i_term - d_term;

  return cmd_;
}

double Pid::computeCommand(double error, double error_dot, ros::Duration dt)
{
  // Get the gain parameters from the realtime buffer
  Gains gains = *gains_buffer_.readFromRT();

  double p_term, d_term, i_term;
  p_error_ = error; // this is error = target - state
  d_error_ = error_dot;

  if (dt == ros::Duration(0.0) || std::isnan(error) || std::isinf(error) || std::isnan(error_dot) || std::isinf(error_dot))
    return 0.0;

  // Calculate proportional contribution to command
  p_term = gains.p_gain_ * p_error_;

  // Calculate the integral of the position error
  i_error_ += dt.toSec() * p_error_;

  // Calculate integral contribution to command
  i_term = gains.i_gain_ * i_error_;

  // Limit i_term so that the limit is meaningful in the output
  i_term = std::max( gains.i_min_, std::min( i_term, gains.i_max_) );

  // Calculate derivative contribution to command
  d_term = gains.d_gain_ * d_error_;

  // Compute the command
  cmd_ = p_term + i_term + d_term;

  return cmd_;
}

double Pid::updatePid(double error, double error_dot, ros::Duration dt)
{
  // Get the gain parameters from the realtime buffer
  Gains gains = *gains_buffer_.readFromRT();

  double p_term, d_term, i_term;
  p_error_ = error; //this is pError = pState-pTarget
  d_error_ = error_dot;

  if (dt == ros::Duration(0.0) || std::isnan(error) || std::isinf(error) || std::isnan(error_dot) || std::isinf(error_dot))
    return 0.0;

  // Calculate proportional contribution to command
  p_term = gains.p_gain_ * p_error_;

  // Calculate the integral of the position error
  i_error_ += dt.toSec() * p_error_;

  // Calculate integral contribution to command
  i_term = gains.i_gain_ * i_error_;

  // Limit i_term so that the limit is meaningful in the output
  i_term = std::max( gains.i_min_, std::min( i_term, gains.i_max_) );

  // Calculate derivative contribution to command
  d_term = gains.d_gain_ * d_error_;

  // Compute the command
  cmd_ = - p_term - i_term - d_term;

  return cmd_;
}

void Pid::setCurrentCmd(double cmd)
{
  cmd_ = cmd;
}

double Pid::getCurrentCmd()
{
  return cmd_;
}

void Pid::getCurrentPIDErrors(double *pe, double *ie, double *de)
{
  // Get the gain parameters from the realtime buffer
  Gains gains = *gains_buffer_.readFromRT();

  *pe = p_error_;
  *ie = i_error_;
  *de = d_error_;
}

void Pid::printValues()
{
  Gains gains = getGains();

  ROS_INFO_STREAM_NAMED("pid","Current Values of PID Class:\n"
    << "  P Gain: " << gains.p_gain_ << "\n"
    << "  I Gain: " << gains.i_gain_ << "\n"
    << "  D Gain: " << gains.d_gain_ << "\n"
    << "  I_Max:  " << gains.i_max_  << "\n"
    << "  I_Min:  " << gains.i_min_  << "\n"
    << "  P_Error_Last: " << p_error_last_  << "\n"
    << "  P_Error:      " << p_error_  << "\n"
    << "  I_Error:       " << i_error_  << "\n"
    << "  D_Error:      " << d_error_  << "\n"
    << "  Command:      " << cmd_
  );

}

} // namespace
<commit_msg>Chain calls of computeCommand and updatePid for code reuse<commit_after>/*********************************************************************
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2008, Willow Garage, Inc.
 *  All rights reserved.
 *
 *  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 Willow Garage 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.
 *********************************************************************/

/*
  Author: Melonee Wise
  Contributors: Dave Coleman, Jonathan Bohren, Bob Holmberg, Wim Meeussen
  Desc: Implements a standard proportional-integral-derivative controller
*/

#include <control_toolbox/pid.h>
#include <tinyxml.h>

namespace control_toolbox {

static const std::string DEFAULT_NAMESPACE = "pid"; // \todo better default prefix?

Pid::Pid(double p, double i, double d, double i_max, double i_min)
  : dynamic_reconfig_initialized_(false)
{
  setGains(p,i,d,i_max,i_min);

  reset();
}

Pid::Pid(const Pid &source)
   : dynamic_reconfig_initialized_(false)
{
  // Copy the realtime buffer to then new PID class
  gains_buffer_ = source.gains_buffer_;

  // Reset the state of this PID controller
  reset();
}

Pid::~Pid()
{
}

void Pid::initPid(double p, double i, double d, double i_max, double i_min,
  const ros::NodeHandle &node)
{
  initPid(p, i, d, i_max, i_min);

  // Create node handle for dynamic reconfigure
  ros::NodeHandle nh(DEFAULT_NAMESPACE);
  initDynamicReconfig(nh);
}

void Pid::initPid(double p, double i, double d, double i_max, double i_min)
{
  setGains(p,i,d,i_max,i_min);

  reset();
}

bool Pid::initParam(const std::string& prefix, const bool quiet)
{
  ros::NodeHandle nh(prefix);
  return init(nh, quiet);
}

bool Pid::init(const ros::NodeHandle &node, const bool quiet)
{
  ros::NodeHandle nh(node);

  Gains gains;

  // Load PID gains from parameter server
  if (!nh.getParam("p", gains.p_gain_))
  {
    if (!quiet) {
      ROS_ERROR("No p gain specified for pid.  Namespace: %s", nh.getNamespace().c_str());
    }
    return false;
  }
  // Only the P gain is required, the I and D gains are optional and default to 0:
  nh.param("i", gains.i_gain_, 0.0);
  nh.param("d", gains.d_gain_, 0.0);

  // Load integral clamp from param server or default to 0
  double i_clamp;
  nh.param("i_clamp", i_clamp, 0.0);
  gains.i_max_ = std::abs(i_clamp);
  gains.i_min_ = -std::abs(i_clamp);
  if(nh.hasParam("i_clamp_min"))
  {
    nh.param("i_clamp_min", gains.i_min_, gains.i_min_); // use i_clamp_min parameter, otherwise keep -i_clamp
    gains.i_min_ = -std::abs(gains.i_min_); // make sure the value is <= 0
  }
  if(nh.hasParam("i_clamp_max"))
  {
    nh.param("i_clamp_max", gains.i_max_, gains.i_max_); // use i_clamp_max parameter, otherwise keep i_clamp
    gains.i_max_ = std::abs(gains.i_max_); // make sure the value is >= 0
  }

  setGains(gains);

  reset();
  initDynamicReconfig(nh);

  return true;
}

bool Pid::initXml(TiXmlElement *config)
{
  // Create node handle for dynamic reconfigure
  ros::NodeHandle nh(DEFAULT_NAMESPACE);

  double i_clamp;
  i_clamp = config->Attribute("iClamp") ? atof(config->Attribute("iClamp")) : 0.0;

  setGains(
    config->Attribute("p") ? atof(config->Attribute("p")) : 0.0,
    config->Attribute("i") ? atof(config->Attribute("i")) : 0.0,
    config->Attribute("d") ? atof(config->Attribute("d")) : 0.0,
    std::abs(i_clamp),
    -std::abs(i_clamp)
  );

  reset();
  initDynamicReconfig(nh);

  return true;
}

void Pid::initDynamicReconfig(ros::NodeHandle &node)
{
  ROS_DEBUG_STREAM_NAMED("pid","Initializing dynamic reconfigure in namespace "
    << node.getNamespace());

  // Start dynamic reconfigure server
  param_reconfig_server_.reset(new DynamicReconfigServer(param_reconfig_mutex_, node));
  dynamic_reconfig_initialized_ = true;

  // Set Dynamic Reconfigure's gains to Pid's values
  updateDynamicReconfig();

  // Set callback
  param_reconfig_callback_ = boost::bind(&Pid::dynamicReconfigCallback, this, _1, _2);
  param_reconfig_server_->setCallback(param_reconfig_callback_);
}

void Pid::reset()
{
  p_error_last_ = 0.0;
  p_error_ = 0.0;
  i_error_ = 0.0;
  d_error_ = 0.0;
  cmd_ = 0.0;
}

void Pid::getGains(double &p, double &i, double &d, double &i_max, double &i_min)
{
  Gains gains = *gains_buffer_.readFromRT();

  p     = gains.p_gain_;
  i     = gains.i_gain_;
  d     = gains.d_gain_;
  i_max = gains.i_max_;
  i_min = gains.i_min_;
}

Pid::Gains Pid::getGains()
{
  return *gains_buffer_.readFromRT();
}

void Pid::setGains(double p, double i, double d, double i_max, double i_min)
{
  Gains gains(p,i,d,i_max,i_min);

  setGains(gains);
}

void Pid::setGains(const Gains &gains)
{
  gains_buffer_.writeFromNonRT(gains);

  // Update dynamic reconfigure with the new gains
  updateDynamicReconfig(gains);
}

void Pid::updateDynamicReconfig()
{
  // Make sure dynamic reconfigure is initialized
  if(!dynamic_reconfig_initialized_)
    return;

  // Get starting values
  control_toolbox::ParametersConfig config;

  // Get starting values
  getGains(config.p, config.i, config.d, config.i_clamp_max, config.i_clamp_min);

  updateDynamicReconfig(config);
}

void Pid::updateDynamicReconfig(Gains gains_config)
{
  // Make sure dynamic reconfigure is initialized
  if(!dynamic_reconfig_initialized_)
    return;

  control_toolbox::ParametersConfig config;

  // Convert to dynamic reconfigure format
  config.p = gains_config.p_gain_;
  config.i = gains_config.i_gain_;
  config.d = gains_config.d_gain_;
  config.i_clamp_max = gains_config.i_max_;
  config.i_clamp_min = gains_config.i_min_;

  updateDynamicReconfig(config);
}

void Pid::updateDynamicReconfig(control_toolbox::ParametersConfig config)
{
  // Make sure dynamic reconfigure is initialized
  if(!dynamic_reconfig_initialized_)
    return;

  // Set starting values, using a shared mutex with dynamic reconfig
  param_reconfig_mutex_.lock();
  param_reconfig_server_->updateConfig(config);
  param_reconfig_mutex_.unlock();
}

void Pid::dynamicReconfigCallback(control_toolbox::ParametersConfig &config, uint32_t level)
{
  ROS_DEBUG_STREAM_NAMED("pid","Dynamics reconfigure callback recieved.");

  // Set the gains
  setGains(config.p, config.i, config.d, config.i_clamp_max, config.i_clamp_min);
}

double Pid::computeCommand(double error, ros::Duration dt)
{

  if (dt == ros::Duration(0.0) || std::isnan(error) || std::isinf(error))
    return 0.0;

  double error_dot = d_error_;

  // Calculate the derivative error
  if (dt.toSec() > 0.0)
  {
    error_dot = (error - p_error_last_) / dt.toSec();
    p_error_last_ = error;
  }

  return computeCommand(error, error_dot, dt);
}

double Pid::updatePid(double error, ros::Duration dt)
{
  if (dt == ros::Duration(0.0) || std::isnan(error) || std::isinf(error))
    return 0.0;

  double error_dot = d_error_;

  // Calculate the derivative error
  if (dt.toSec() > 0.0)
  {
    error_dot = (error - p_error_last_) / dt.toSec();
    p_error_last_ = error;
  }

  return updatePid(error, error_dot, dt);
}

double Pid::computeCommand(double error, double error_dot, ros::Duration dt)
{
  // Get the gain parameters from the realtime buffer
  Gains gains = *gains_buffer_.readFromRT();

  double p_term, d_term, i_term;
  p_error_ = error; // this is error = target - state
  d_error_ = error_dot;

  if (dt == ros::Duration(0.0) || std::isnan(error) || std::isinf(error) || std::isnan(error_dot) || std::isinf(error_dot))
    return 0.0;

  // Calculate proportional contribution to command
  p_term = gains.p_gain_ * p_error_;

  // Calculate the integral of the position error
  i_error_ += dt.toSec() * p_error_;

  // Calculate integral contribution to command
  i_term = gains.i_gain_ * i_error_;

  // Limit i_term so that the limit is meaningful in the output
  i_term = std::max( gains.i_min_, std::min( i_term, gains.i_max_) );

  // Calculate derivative contribution to command
  d_term = gains.d_gain_ * d_error_;

  // Compute the command
  cmd_ = p_term + i_term + d_term;

  return cmd_;
}

double Pid::updatePid(double error, double error_dot, ros::Duration dt)
{
  // Get the gain parameters from the realtime buffer
  Gains gains = *gains_buffer_.readFromRT();

  double p_term, d_term, i_term;
  p_error_ = error; //this is pError = pState-pTarget
  d_error_ = error_dot;

  if (dt == ros::Duration(0.0) || std::isnan(error) || std::isinf(error) || std::isnan(error_dot) || std::isinf(error_dot))
    return 0.0;

  // Calculate proportional contribution to command
  p_term = gains.p_gain_ * p_error_;

  // Calculate the integral of the position error
  i_error_ += dt.toSec() * p_error_;

  // Calculate integral contribution to command
  i_term = gains.i_gain_ * i_error_;

  // Limit i_term so that the limit is meaningful in the output
  i_term = std::max( gains.i_min_, std::min( i_term, gains.i_max_) );

  // Calculate derivative contribution to command
  d_term = gains.d_gain_ * d_error_;

  // Compute the command
  cmd_ = - p_term - i_term - d_term;

  return cmd_;
}

void Pid::setCurrentCmd(double cmd)
{
  cmd_ = cmd;
}

double Pid::getCurrentCmd()
{
  return cmd_;
}

void Pid::getCurrentPIDErrors(double *pe, double *ie, double *de)
{
  // Get the gain parameters from the realtime buffer
  Gains gains = *gains_buffer_.readFromRT();

  *pe = p_error_;
  *ie = i_error_;
  *de = d_error_;
}

void Pid::printValues()
{
  Gains gains = getGains();

  ROS_INFO_STREAM_NAMED("pid","Current Values of PID Class:\n"
    << "  P Gain: " << gains.p_gain_ << "\n"
    << "  I Gain: " << gains.i_gain_ << "\n"
    << "  D Gain: " << gains.d_gain_ << "\n"
    << "  I_Max:  " << gains.i_max_  << "\n"
    << "  I_Min:  " << gains.i_min_  << "\n"
    << "  P_Error_Last: " << p_error_last_  << "\n"
    << "  P_Error:      " << p_error_  << "\n"
    << "  I_Error:       " << i_error_  << "\n"
    << "  D_Error:      " << d_error_  << "\n"
    << "  Command:      " << cmd_
  );

}

} // namespace
<|endoftext|>


<commit_before>#include <iostream>
#include <unistd.h>
#include <linux/version.h>

#include "libbpf.h"
#include "utils.h"

#include "map.h"

namespace bpftrace {

int Map::create_map(enum bpf_map_type map_type, const char *name, int key_size, int value_size, int max_entries, int flags) {
#ifdef HAVE_BCC_CREATE_MAP
  return bcc_create_map(map_type, name, key_size, value_size, max_entries, flags);
#else
  return bpf_create_map(map_type, name, key_size, value_size, max_entries, flags);
#endif
}

Map::Map(const std::string &name, const SizedType &type, const MapKey &key, int min, int max, int step)
{
  name_ = name;
  type_ = type;
  key_ = key;
  // for lhist maps:
  lqmin = min;
  lqmax = max;
  lqstep = step;

  int key_size = key.size();
  if (type.type == Type::hist || type.type == Type::lhist ||
      type.type == Type::avg || type.type == Type::stats)
    key_size += 8;
  if (key_size == 0)
    key_size = 8;

  int max_entries = 128;
  enum bpf_map_type map_type;
  if ((type.type == Type::hist || type.type == Type::lhist || type.type == Type::count ||
      type.type == Type::sum || type.type == Type::min || type.type == Type::max ||
      type.type == Type::avg || type.type == Type::stats) &&
      (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0)))
  {
      map_type = BPF_MAP_TYPE_PERCPU_HASH;
  }
  else if (type.type == Type::join)
  {
    map_type = BPF_MAP_TYPE_PERCPU_ARRAY;
    max_entries = 1;
    key_size = 4;
  }
  else
    map_type = BPF_MAP_TYPE_HASH;

  int value_size = type.size;
  int flags = 0;
  mapfd_ = create_map(map_type, name.c_str(), key_size, value_size, max_entries, flags);
  if (mapfd_ < 0)
  {
    std::cerr << "Error creating map: '" << name_ << "'" << std::endl;
  }
}

Map::Map(const SizedType &type) {
#ifdef DEBUG
  // TODO (mmarchini): replace with DCHECK
  if (!type.IsStack()) {
    std::cerr << "Map::Map(SizedType) constructor should be called only with stack types" << std::endl;
    abort()
  }
#endif
  type_ = type;
  int key_size = 4;
  int value_size = sizeof(uintptr_t) * type.stack_type.limit;
  std::string name = "stack";
  int max_entries = 4096;
  int flags = 0;
  enum bpf_map_type map_type = BPF_MAP_TYPE_STACK_TRACE;

  mapfd_ = create_map(map_type, name.c_str(), key_size, value_size, max_entries, flags);
  if (mapfd_ < 0)
  {
    std::cerr << "Error creating stack id map" << std::endl;
    // TODO (mmarchini): Check perf_event_max_stack in the semantic_analyzer
    std::cerr << "This might have happened because kernel.perf_event_max_stack"
      << "is smaller than " << type.stack_type.limit
      << ". Try to tweak this value with"
      << "sysctl kernel.perf_event_max_stack=<new value>" << std::endl;
  }
}

Map::Map(enum bpf_map_type map_type)
{
  int key_size, value_size, max_entries, flags;

  std::string name;
#ifdef DEBUG
  // TODO (mmarchini): replace with DCHECK
  if (map_type == BPF_MAP_TYPE_STACK_TRACE)
  {
    std::cerr << "Use Map::Map(SizedType) constructor instead" << std::endl;
    abort();
  }
#endif
  if (map_type == BPF_MAP_TYPE_PERF_EVENT_ARRAY)
  {
    std::vector<int> cpus = get_online_cpus();
    name = "printf";
    key_size = 4;
    value_size = 4;
    max_entries = cpus.size();
    flags = 0;
  }
  else
  {
    std::cerr << "invalid map type" << std::endl;
    abort();
  }

  mapfd_ = create_map(map_type, name.c_str(), key_size, value_size, max_entries, flags);
  if (mapfd_ < 0)
  {
    std::string name;
    switch (map_type)
    {
      case BPF_MAP_TYPE_PERF_EVENT_ARRAY:
        name = "perf event";
        break;
      default:
        std::cerr << "invalid map type" << std::endl;
        abort();
    }

    std::cerr << "Error creating " << name << " map (" << mapfd_ << ")" << std::endl;
  }
}

Map::~Map()
{
  if (mapfd_ >= 0)
    close(mapfd_);
}

} // namespace bpftrace
<commit_msg>Add missing space to error message<commit_after>#include <iostream>
#include <unistd.h>
#include <linux/version.h>

#include "libbpf.h"
#include "utils.h"

#include "map.h"

namespace bpftrace {

int Map::create_map(enum bpf_map_type map_type, const char *name, int key_size, int value_size, int max_entries, int flags) {
#ifdef HAVE_BCC_CREATE_MAP
  return bcc_create_map(map_type, name, key_size, value_size, max_entries, flags);
#else
  return bpf_create_map(map_type, name, key_size, value_size, max_entries, flags);
#endif
}

Map::Map(const std::string &name, const SizedType &type, const MapKey &key, int min, int max, int step)
{
  name_ = name;
  type_ = type;
  key_ = key;
  // for lhist maps:
  lqmin = min;
  lqmax = max;
  lqstep = step;

  int key_size = key.size();
  if (type.type == Type::hist || type.type == Type::lhist ||
      type.type == Type::avg || type.type == Type::stats)
    key_size += 8;
  if (key_size == 0)
    key_size = 8;

  int max_entries = 128;
  enum bpf_map_type map_type;
  if ((type.type == Type::hist || type.type == Type::lhist || type.type == Type::count ||
      type.type == Type::sum || type.type == Type::min || type.type == Type::max ||
      type.type == Type::avg || type.type == Type::stats) &&
      (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0)))
  {
      map_type = BPF_MAP_TYPE_PERCPU_HASH;
  }
  else if (type.type == Type::join)
  {
    map_type = BPF_MAP_TYPE_PERCPU_ARRAY;
    max_entries = 1;
    key_size = 4;
  }
  else
    map_type = BPF_MAP_TYPE_HASH;

  int value_size = type.size;
  int flags = 0;
  mapfd_ = create_map(map_type, name.c_str(), key_size, value_size, max_entries, flags);
  if (mapfd_ < 0)
  {
    std::cerr << "Error creating map: '" << name_ << "'" << std::endl;
  }
}

Map::Map(const SizedType &type) {
#ifdef DEBUG
  // TODO (mmarchini): replace with DCHECK
  if (!type.IsStack()) {
    std::cerr << "Map::Map(SizedType) constructor should be called only with stack types" << std::endl;
    abort()
  }
#endif
  type_ = type;
  int key_size = 4;
  int value_size = sizeof(uintptr_t) * type.stack_type.limit;
  std::string name = "stack";
  int max_entries = 4096;
  int flags = 0;
  enum bpf_map_type map_type = BPF_MAP_TYPE_STACK_TRACE;

  mapfd_ = create_map(map_type, name.c_str(), key_size, value_size, max_entries, flags);
  if (mapfd_ < 0)
  {
    std::cerr << "Error creating stack id map" << std::endl;
    // TODO (mmarchini): Check perf_event_max_stack in the semantic_analyzer
    std::cerr << "This might have happened because kernel.perf_event_max_stack"
      << "is smaller than " << type.stack_type.limit
      << ". Try to tweak this value with "
      << "sysctl kernel.perf_event_max_stack=<new value>" << std::endl;
  }
}

Map::Map(enum bpf_map_type map_type)
{
  int key_size, value_size, max_entries, flags;

  std::string name;
#ifdef DEBUG
  // TODO (mmarchini): replace with DCHECK
  if (map_type == BPF_MAP_TYPE_STACK_TRACE)
  {
    std::cerr << "Use Map::Map(SizedType) constructor instead" << std::endl;
    abort();
  }
#endif
  if (map_type == BPF_MAP_TYPE_PERF_EVENT_ARRAY)
  {
    std::vector<int> cpus = get_online_cpus();
    name = "printf";
    key_size = 4;
    value_size = 4;
    max_entries = cpus.size();
    flags = 0;
  }
  else
  {
    std::cerr << "invalid map type" << std::endl;
    abort();
  }

  mapfd_ = create_map(map_type, name.c_str(), key_size, value_size, max_entries, flags);
  if (mapfd_ < 0)
  {
    std::string name;
    switch (map_type)
    {
      case BPF_MAP_TYPE_PERF_EVENT_ARRAY:
        name = "perf event";
        break;
      default:
        std::cerr << "invalid map type" << std::endl;
        abort();
    }

    std::cerr << "Error creating " << name << " map (" << mapfd_ << ")" << std::endl;
  }
}

Map::~Map()
{
  if (mapfd_ >= 0)
    close(mapfd_);
}

} // namespace bpftrace
<|endoftext|>


<commit_before>#include <iostream>
#include "io.h"
#include "matrix.impl.h"
#include "worker.h"
#include <chrono>

int main(int argc, char** argv){
    int width, height;
    std::vector<std::string> map;

    // Reads a file
    IO::readFile(width, height, map);

    std::shared_ptr<Matrix<char> > crossword = std::make_shared<Matrix<char> >(width, height);
    std::shared_ptr<Matrix<bool> > visited = std::make_shared<Matrix<bool> >(width, height);

    for (auto i = 0; i < width; ++i) {
        for (auto j = 0; j < height; ++j) {
            crossword->set(i, j, map.at(i).at(j));
            visited->set(i, j, false);
        }
    }

    auto start = std::chrono::high_resolution_clock::now();

    //Worker work("threads", crossword);
    Worker work1("threads", crossword);
    Worker work2("arquivos", crossword);
    Worker work3("sinais", crossword);
    Worker work4("pipe", crossword);
    Worker work5("processos", crossword);
    Worker work6("mutex", crossword);

    work1.join();
    work2.join();
    work3.join();
    work4.join();
    work5.join();
    work6.join();

    auto end = std::chrono::high_resolution_clock::now();
    auto elapsed = std::chrono::duration_cast<std::chrono::microseconds>(end - start);

    std::cout << "took " << elapsed.count() << " microseconds." << std::endl;

    std::cout << *crossword << std::endl;
    return 0;
}
<commit_msg>working<commit_after>#include <iostream>
#include "io.h"
#include "matrix.impl.h"
#include "worker.h"
#include <chrono>

int main(int argc, char** argv){
    int width, height;
    std::vector<std::string> map;

    // Reads a file
    IO::readFile(width, height, map);

    std::shared_ptr<Matrix<char> > crossword = std::make_shared<Matrix<char> >(width, height);

    for (auto i = 0; i < width; ++i) {
        for (auto j = 0; j < height; ++j) {
            crossword->set(i, j, map.at(i).at(j));
        }
    }

    std::cout << *crossword << std::endl;

    unsigned int numThreads;

    std::vector<std::string> words = {"threads", "arquivos", "sinais", "pipe", "processos", "mutex"};

    std::vector<std::shared_ptr<Worker> > workers;

    do {
        std::cout << "Numero de threads (Cada thread procura uma palavra)" << std::endl;
        std::cin >> numThreads;
    } while (!(numThreads < words.size() && numThreads > 0));

    auto start = std::chrono::high_resolution_clock::now();

    for (auto i = 0u; i <= words.size() - numThreads; i+=numThreads) {
        for (auto j = i; j < i + numThreads; ++j) {
            workers.push_back(std::make_shared<Worker>(words.at(j), crossword));
        }

        for (auto& worker : workers) {
            worker->join();
        }

        workers.clear();
    }

    auto end = std::chrono::high_resolution_clock::now();
    auto elapsed = std::chrono::duration_cast<std::chrono::microseconds>(end - start);

    std::cout << "took " << elapsed.count() << " microseconds." << std::endl;

    std::cout << *crossword << std::endl;
    return 0;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <fstream>
#include <chrono>
#include <thread>

#include "chip8core/Emulator.h"

#include "curses.h"

using namespace std;
using namespace chip8curses;

int constexpr KEY_ESCAPE{27};

int main(int argc, char* argv[]) {
  if (argc != 2) {
    cerr << "Usage: " << argv[0] << " FILENAME\n";
    return 1;
  }

  Emulator chip8core;
  if (!chip8core.loadFileToRam(argv[1])) {
    cerr << argv[0] << ": Error loading file: " << chip8core.getError() << "\n";
    return 1;
  }

  curses::start(Emulator::screen_rows, Emulator::screen_columns);
  curses::attach(&chip8core);
  vector<bool> keys(Emulator::num_keys);

  bool loop = true;
  while (loop) {
    chip8core.tick();
    std::this_thread::sleep_for(std::chrono::milliseconds(10));

    switch (curses::get_char()) {
      case KEY_ESCAPE:
        loop = false;
        break;

      case '1': chip8core.setKeyState(0x0, (keys.at(0x0) = !keys.at(0x0))); break;
      case '2': chip8core.setKeyState(0x1, (keys.at(0x1) = !keys.at(0x1))); break;
      case '3': chip8core.setKeyState(0x2, (keys.at(0x2) = !keys.at(0x2))); break;
      case '4': chip8core.setKeyState(0x3, (keys.at(0x3) = !keys.at(0x3))); break;
      case 'q': chip8core.setKeyState(0x4, (keys.at(0x4) = !keys.at(0x4))); break;
      case 'w': chip8core.setKeyState(0x5, (keys.at(0x5) = !keys.at(0x5))); break;
      case 'e': chip8core.setKeyState(0x6, (keys.at(0x6) = !keys.at(0x6))); break;
      case 'r': chip8core.setKeyState(0x7, (keys.at(0x7) = !keys.at(0x7))); break;
      case 'a': chip8core.setKeyState(0x8, (keys.at(0x8) = !keys.at(0x8))); break;
      case 's': chip8core.setKeyState(0x9, (keys.at(0x9) = !keys.at(0x9))); break;
      case 'd': chip8core.setKeyState(0xA, (keys.at(0xA) = !keys.at(0xA))); break;
      case 'f': chip8core.setKeyState(0xB, (keys.at(0xB) = !keys.at(0xB))); break;
      case 'z': chip8core.setKeyState(0xC, (keys.at(0xC) = !keys.at(0xC))); break;
      case 'x': chip8core.setKeyState(0xD, (keys.at(0xD) = !keys.at(0xD))); break;
      case 'c': chip8core.setKeyState(0xE, (keys.at(0xE) = !keys.at(0xE))); break;
      case 'v': chip8core.setKeyState(0xF, (keys.at(0xF) = !keys.at(0xF))); break;
    }

  }

  curses::stop();
  return 0;
}
<commit_msg>Fix keyboard layout<commit_after>#include <iostream>
#include <fstream>
#include <chrono>
#include <thread>

#include "chip8core/Emulator.h"

#include "curses.h"

using namespace std;
using namespace chip8curses;

int constexpr KEY_ESCAPE{27};

int main(int argc, char* argv[]) {
  if (argc != 2) {
    cerr << "Usage: " << argv[0] << " FILENAME\n";
    return 1;
  }

  Emulator chip8core;
  if (!chip8core.loadFileToRam(argv[1])) {
    cerr << argv[0] << ": Error loading file: " << chip8core.getError() << "\n";
    return 1;
  }

  curses::start(Emulator::screen_rows, Emulator::screen_columns);
  curses::attach(&chip8core);
  vector<bool> keys(Emulator::num_keys);

  bool loop = true;
  while (loop) {
    chip8core.tick();
    std::this_thread::sleep_for(std::chrono::milliseconds(10));

    switch (curses::get_char()) {
      case KEY_ESCAPE:
        loop = false;
        break;

      case 'x': chip8core.setKeyState(0x0, (keys.at(0x0) = !keys.at(0x0))); break;
      case '1': chip8core.setKeyState(0x1, (keys.at(0x1) = !keys.at(0x1))); break;
      case '2': chip8core.setKeyState(0x2, (keys.at(0x2) = !keys.at(0x2))); break;
      case '3': chip8core.setKeyState(0x3, (keys.at(0x3) = !keys.at(0x3))); break;
      case 'q': chip8core.setKeyState(0x4, (keys.at(0x4) = !keys.at(0x4))); break;
      case 'w': chip8core.setKeyState(0x5, (keys.at(0x5) = !keys.at(0x5))); break;
      case 'e': chip8core.setKeyState(0x6, (keys.at(0x6) = !keys.at(0x6))); break;
      case 'a': chip8core.setKeyState(0x7, (keys.at(0x7) = !keys.at(0x7))); break;
      case 's': chip8core.setKeyState(0x8, (keys.at(0x8) = !keys.at(0x8))); break;
      case 'd': chip8core.setKeyState(0x9, (keys.at(0x9) = !keys.at(0x9))); break;
      case 'z': chip8core.setKeyState(0xA, (keys.at(0xA) = !keys.at(0xA))); break;
      case 'c': chip8core.setKeyState(0xB, (keys.at(0xB) = !keys.at(0xB))); break;
      case '4': chip8core.setKeyState(0xC, (keys.at(0xC) = !keys.at(0xC))); break;
      case 'r': chip8core.setKeyState(0xD, (keys.at(0xD) = !keys.at(0xD))); break;
      case 'f': chip8core.setKeyState(0xE, (keys.at(0xE) = !keys.at(0xE))); break;
      case 'v': chip8core.setKeyState(0xF, (keys.at(0xF) = !keys.at(0xF))); break;
    }

  }

  curses::stop();
  return 0;
}
<|endoftext|>


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

#include "pow.h"

#include "arith_uint256.h"
#include "chain.h"
#include "primitives/block.h"
#include "uint256.h"
#include "util.h"
#include <cmath>

static const int64_t nDiffChangeTarget = 56000; // Patch effective @ block 56000

unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params)
{
    int nHeight = pindexLast->nHeight + 1;
    bool fNewDifficultyProtocol = (nHeight >= nDiffChangeTarget);

    if (fNewDifficultyProtocol || params.fPowAllowMinDifficultyBlocks) {
        return DigiShield(pindexLast, pblock, params);
    }
    else {

        static const int64_t	            	 BlocksTargetSpacing                          = 60; // 1 minute
        unsigned int                             TimeDaySeconds                               = 60 * 60 * 24;
        int64_t                                  PastSecondsMin                               = TimeDaySeconds * 0.25;
        int64_t                                  PastSecondsMax                               = TimeDaySeconds * 7;
        uint64_t                                 PastBlocksMin                                = PastSecondsMin / BlocksTargetSpacing;
        uint64_t                                 PastBlocksMax                                = PastSecondsMax / BlocksTargetSpacing;
        return KimotoGravityWell(pindexLast, pblock, BlocksTargetSpacing, PastBlocksMin, PastBlocksMax, params);
    }
}

unsigned int DigiShield(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params)
{
    unsigned int nProofOfWorkLimit = UintToArith256(params.powLimit).GetCompact();

    // Genesis block
    if (pindexLast == NULL)
        return nProofOfWorkLimit;

    // Only change once per interval
    if ((pindexLast->nHeight+1) % params.DifficultyAdjustmentInterval() != 0)
    {
        if (params.fPowAllowMinDifficultyBlocks)
        {
            // Special difficulty rule for testnet:
            // If the new block's timestamp is more than 2* 10 minutes
            // then allow mining of a min-difficulty block.
            if (pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.nPowTargetSpacing*2)
                return nProofOfWorkLimit;
            else
            {
                // Return the last non-special-min-difficulty-rules-block
                const CBlockIndex* pindex = pindexLast;
                while (pindex->pprev && pindex->nHeight % params.DifficultyAdjustmentInterval() != 0 && pindex->nBits == nProofOfWorkLimit)
                    pindex = pindex->pprev;
                return pindex->nBits;
            }
         }
        return pindexLast->nBits;
    }

    // Litecoin: This fixes an issue where a 51% attack can change difficulty at will.
    // Go back the full period unless it's the first retarget after genesis. Code courtesy of Art Forz
    int blockstogoback = params.DifficultyAdjustmentInterval()-1;
    if ((pindexLast->nHeight+1) != params.DifficultyAdjustmentInterval())
        blockstogoback = params.DifficultyAdjustmentInterval();

    // Go back by what we want to be 14 days worth of blocks
    const CBlockIndex* pindexFirst = pindexLast;
    for (int i = 0; pindexFirst && i < blockstogoback; i++)
        pindexFirst = pindexFirst->pprev;
    assert(pindexFirst);

    return CalculateNextWorkRequired(pindexLast, pindexFirst->GetBlockTime(), params);
}

unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params& params)
{
    if (params.fPowNoRetargeting)
        return pindexLast->nBits;

    // Limit adjustment step
    int64_t nActualTimespan = pindexLast->GetBlockTime() - nFirstBlockTime;

    arith_uint256 bnNew;
    bnNew.SetCompact(pindexLast->nBits);

//DigiShield implementation - thanks to RealSolid & WDC for this code
//amplitude filter - thanks to daft27 for this code
        nActualTimespan = params.nPowTargetTimespan + (nActualTimespan - params.nPowTargetTimespan)/8;
        if (nActualTimespan < (params.nPowTargetTimespan - (params.nPowTargetTimespan/4)) ) nActualTimespan = (params.nPowTargetTimespan - (params.nPowTargetTimespan/4));
        if (nActualTimespan > (params.nPowTargetTimespan + (params.nPowTargetTimespan/2)) ) nActualTimespan = (params.nPowTargetTimespan + (params.nPowTargetTimespan/2));
    // Retarget

        bnNew *= nActualTimespan;
        bnNew /= params.nPowTargetTimespan;

        const arith_uint256 bnPowLimit = UintToArith256(params.powLimit);
        if (bnNew > bnPowLimit)
            bnNew = bnPowLimit;

    /// debug print
    // LogPrintf("GetNextWorkRequired: DIGISHIELD RETARGET\n");
    return bnNew.GetCompact();
}

bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params& params)
{
    bool fNegative;
    bool fOverflow;
    arith_uint256 bnTarget;

    bnTarget.SetCompact(nBits, &fNegative, &fOverflow);

    // Check range
    if (fNegative || bnTarget == 0 || fOverflow || bnTarget > UintToArith256(params.powLimit))
        return false;

    // Check proof of work matches claimed amount
    if (UintToArith256(hash) > bnTarget)
        return false;

    return true;
}

unsigned int KimotoGravityWell(const CBlockIndex* pindexLast, const CBlockHeader *pblock, uint64_t TargetBlocksSpacingSeconds, uint64_t PastBlocksMin, uint64_t PastBlocksMax, const Consensus::Params& params)
{
        /* current difficulty formula - kimoto gravity well */
        const CBlockIndex *BlockLastSolved                                         = pindexLast;
        const CBlockIndex *BlockReading                                            = pindexLast;

        uint64_t                              PastBlocksMass                       = 0;
        int64_t                               PastRateActualSeconds                = 0;
        int64_t                               PastRateTargetSeconds                = 0;
        double                                PastRateAdjustmentRatio              = double(1);
        arith_uint256                         PastDifficultyAverage;
        arith_uint256                         PastDifficultyAveragePrev;
        double                                EventHorizonDeviation;
        double                                EventHorizonDeviationFast;
        double                                EventHorizonDeviationSlow;
        const arith_uint256 bnPowLimit = UintToArith256(params.powLimit);

        if (BlockLastSolved == NULL || BlockLastSolved->nHeight == 0 || (uint64_t)BlockLastSolved->nHeight < PastBlocksMin) { return bnPowLimit.GetCompact(); }

        for (unsigned int i = 1; BlockReading && BlockReading->nHeight > 0; i++) {
                if (PastBlocksMax > 0 && i > PastBlocksMax) { break; }
                PastBlocksMass++;

                if (i == 1)        { PastDifficultyAverage.SetCompact(BlockReading->nBits); }
                else             //Einsteinium: workaround were to overcome the overflow issue when changing from CBigNum to arith_uint256
                                    if (arith_uint256().SetCompact(BlockReading->nBits) >= PastDifficultyAveragePrev)
                                    PastDifficultyAverage = ((arith_uint256().SetCompact(BlockReading->nBits) - PastDifficultyAveragePrev) / i) + PastDifficultyAveragePrev;
                                    else
                                    PastDifficultyAverage = PastDifficultyAveragePrev - ((PastDifficultyAveragePrev - arith_uint256().SetCompact(BlockReading->nBits)) / i);

                PastDifficultyAveragePrev = PastDifficultyAverage;

                PastRateActualSeconds                        = BlockLastSolved->GetBlockTime() - BlockReading->GetBlockTime();
                PastRateTargetSeconds                        = TargetBlocksSpacingSeconds * PastBlocksMass;
                PastRateAdjustmentRatio                        = double(1);
                if (PastRateActualSeconds < 0) { PastRateActualSeconds = 0; }
                if (PastRateActualSeconds != 0 && PastRateTargetSeconds != 0) {
                PastRateAdjustmentRatio                        = double(PastRateTargetSeconds) / double(PastRateActualSeconds);
                }
                EventHorizonDeviation                        = 1 + (0.7084 * pow((double(PastBlocksMass)/double(144)), -1.228));
                EventHorizonDeviationFast                = EventHorizonDeviation;
                EventHorizonDeviationSlow                = 1 / EventHorizonDeviation;

                if (PastBlocksMass >= PastBlocksMin) {
                        if ((PastRateAdjustmentRatio <= EventHorizonDeviationSlow) || (PastRateAdjustmentRatio >= EventHorizonDeviationFast)) { assert(BlockReading); break; }
                }
                if (BlockReading->pprev == NULL) { assert(BlockReading); break; }
                BlockReading = BlockReading->pprev;
        }

        arith_uint256 bnNew(PastDifficultyAverage);

        if (PastRateActualSeconds != 0 && PastRateTargetSeconds != 0) {
            // LogPrintf("Difficulty Retarget - Kimoto Gravity Well\n");
            bnNew *= PastRateActualSeconds;
            bnNew /= PastRateTargetSeconds;
       }
        if (bnNew > bnPowLimit)
            bnNew = bnPowLimit;

/* debug print (commented out due to spamming logs when the loop above breaks)
   printf("Difficulty Retarget - Kimoto Gravity Well\n");
   printf("PastRateAdjustmentRatio = %g\n", PastRateAdjustmentRatio);
   printf("Before: %08x %s\n", BlockLastSolved->nBits, arith_uint256().SetCompact(BlockLastSolved->nBits).ToString().c_str());
   printf("After: %08x %s\n", bnNew.GetCompact(), bnNew.ToString().c_str());
*/

        return bnNew.GetCompact();
}

<commit_msg>Add intermediate overflow prevention<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2016 The Bitcoin Core developers
// Copyright (c) 2017 PM-Tech
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "pow.h"

#include "arith_uint256.h"
#include "chain.h"
#include "primitives/block.h"
#include "uint256.h"
#include "util.h"
#include <cmath>

static const int64_t nDiffChangeTarget = 56000; // Patch effective @ block 56000

unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params)
{
    int nHeight = pindexLast->nHeight + 1;
    bool fNewDifficultyProtocol = (nHeight >= nDiffChangeTarget);

    if (fNewDifficultyProtocol || params.fPowAllowMinDifficultyBlocks) {
        return DigiShield(pindexLast, pblock, params);
    }
    else {

        static const int64_t	            	 BlocksTargetSpacing                          = 60; // 1 minute
        unsigned int                             TimeDaySeconds                               = 60 * 60 * 24;
        int64_t                                  PastSecondsMin                               = TimeDaySeconds * 0.25;
        int64_t                                  PastSecondsMax                               = TimeDaySeconds * 7;
        uint64_t                                 PastBlocksMin                                = PastSecondsMin / BlocksTargetSpacing;
        uint64_t                                 PastBlocksMax                                = PastSecondsMax / BlocksTargetSpacing;
        return KimotoGravityWell(pindexLast, pblock, BlocksTargetSpacing, PastBlocksMin, PastBlocksMax, params);
    }
}

unsigned int DigiShield(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params)
{
    unsigned int nProofOfWorkLimit = UintToArith256(params.powLimit).GetCompact();

    // Genesis block
    if (pindexLast == NULL)
        return nProofOfWorkLimit;

    // Only change once per interval
    if ((pindexLast->nHeight+1) % params.DifficultyAdjustmentInterval() != 0)
    {
        if (params.fPowAllowMinDifficultyBlocks)
        {
            // Special difficulty rule for testnet:
            // If the new block's timestamp is more than 2* 10 minutes
            // then allow mining of a min-difficulty block.
            if (pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.nPowTargetSpacing*2)
                return nProofOfWorkLimit;
            else
            {
                // Return the last non-special-min-difficulty-rules-block
                const CBlockIndex* pindex = pindexLast;
                while (pindex->pprev && pindex->nHeight % params.DifficultyAdjustmentInterval() != 0 && pindex->nBits == nProofOfWorkLimit)
                    pindex = pindex->pprev;
                return pindex->nBits;
            }
         }
        return pindexLast->nBits;
    }

    // Litecoin: This fixes an issue where a 51% attack can change difficulty at will.
    // Go back the full period unless it's the first retarget after genesis. Code courtesy of Art Forz
    int blockstogoback = params.DifficultyAdjustmentInterval()-1;
    if ((pindexLast->nHeight+1) != params.DifficultyAdjustmentInterval())
        blockstogoback = params.DifficultyAdjustmentInterval();

    // Go back by what we want to be 14 days worth of blocks
    const CBlockIndex* pindexFirst = pindexLast;
    for (int i = 0; pindexFirst && i < blockstogoback; i++)
        pindexFirst = pindexFirst->pprev;
    assert(pindexFirst);

    return CalculateNextWorkRequired(pindexLast, pindexFirst->GetBlockTime(), params);
}

unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params& params)
{
    if (params.fPowNoRetargeting)
        return pindexLast->nBits;

    // Limit adjustment step
    int64_t nActualTimespan = pindexLast->GetBlockTime() - nFirstBlockTime;

    arith_uint256 bnNew;
    bnNew.SetCompact(pindexLast->nBits);

//DigiShield implementation - thanks to RealSolid & WDC for this code
//amplitude filter - thanks to daft27 for this code
        nActualTimespan = params.nPowTargetTimespan + (nActualTimespan - params.nPowTargetTimespan)/8;
        if (nActualTimespan < (params.nPowTargetTimespan - (params.nPowTargetTimespan/4)) ) nActualTimespan = (params.nPowTargetTimespan - (params.nPowTargetTimespan/4));
        if (nActualTimespan > (params.nPowTargetTimespan + (params.nPowTargetTimespan/2)) ) nActualTimespan = (params.nPowTargetTimespan + (params.nPowTargetTimespan/2));
    // Retarget

        // Litecoin: intermediate uint256 can overflow by 1 bit
        const arith_uint256 bnPowLimit = UintToArith256(params.powLimit);
        bool fShift = bnNew.bits() > bnPowLimit.bits() - 1;
        if (fShift)
              bnNew >>= 1;
        bnNew *= nActualTimespan;
        bnNew /= params.nPowTargetTimespan;
        if (fShift)
              bnNew <<= 1;

        if (bnNew > bnPowLimit)
            bnNew = bnPowLimit;

    /// debug print
    // LogPrintf("GetNextWorkRequired: DIGISHIELD RETARGET\n");
    return bnNew.GetCompact();
}

bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params& params)
{
    bool fNegative;
    bool fOverflow;
    arith_uint256 bnTarget;

    bnTarget.SetCompact(nBits, &fNegative, &fOverflow);

    // Check range
    if (fNegative || bnTarget == 0 || fOverflow || bnTarget > UintToArith256(params.powLimit))
        return false;

    // Check proof of work matches claimed amount
    if (UintToArith256(hash) > bnTarget)
        return false;

    return true;
}

unsigned int KimotoGravityWell(const CBlockIndex* pindexLast, const CBlockHeader *pblock, uint64_t TargetBlocksSpacingSeconds, uint64_t PastBlocksMin, uint64_t PastBlocksMax, const Consensus::Params& params)
{
        /* current difficulty formula - kimoto gravity well */
        const CBlockIndex *BlockLastSolved                                         = pindexLast;
        const CBlockIndex *BlockReading                                            = pindexLast;

        uint64_t                              PastBlocksMass                       = 0;
        int64_t                               PastRateActualSeconds                = 0;
        int64_t                               PastRateTargetSeconds                = 0;
        double                                PastRateAdjustmentRatio              = double(1);
        arith_uint256                         PastDifficultyAverage;
        arith_uint256                         PastDifficultyAveragePrev;
        double                                EventHorizonDeviation;
        double                                EventHorizonDeviationFast;
        double                                EventHorizonDeviationSlow;
        const arith_uint256 bnPowLimit = UintToArith256(params.powLimit);

        if (BlockLastSolved == NULL || BlockLastSolved->nHeight == 0 || (uint64_t)BlockLastSolved->nHeight < PastBlocksMin) { return bnPowLimit.GetCompact(); }

        for (unsigned int i = 1; BlockReading && BlockReading->nHeight > 0; i++) {
                if (PastBlocksMax > 0 && i > PastBlocksMax) { break; }
                PastBlocksMass++;

                if (i == 1)        { PastDifficultyAverage.SetCompact(BlockReading->nBits); }
                else             //Einsteinium: workaround were to overcome the overflow issue when changing from CBigNum to arith_uint256
                                    if (arith_uint256().SetCompact(BlockReading->nBits) >= PastDifficultyAveragePrev)
                                    PastDifficultyAverage = ((arith_uint256().SetCompact(BlockReading->nBits) - PastDifficultyAveragePrev) / i) + PastDifficultyAveragePrev;
                                    else
                                    PastDifficultyAverage = PastDifficultyAveragePrev - ((PastDifficultyAveragePrev - arith_uint256().SetCompact(BlockReading->nBits)) / i);

                PastDifficultyAveragePrev = PastDifficultyAverage;

                PastRateActualSeconds                        = BlockLastSolved->GetBlockTime() - BlockReading->GetBlockTime();
                PastRateTargetSeconds                        = TargetBlocksSpacingSeconds * PastBlocksMass;
                PastRateAdjustmentRatio                        = double(1);
                if (PastRateActualSeconds < 0) { PastRateActualSeconds = 0; }
                if (PastRateActualSeconds != 0 && PastRateTargetSeconds != 0) {
                PastRateAdjustmentRatio                        = double(PastRateTargetSeconds) / double(PastRateActualSeconds);
                }
                EventHorizonDeviation                        = 1 + (0.7084 * pow((double(PastBlocksMass)/double(144)), -1.228));
                EventHorizonDeviationFast                = EventHorizonDeviation;
                EventHorizonDeviationSlow                = 1 / EventHorizonDeviation;

                if (PastBlocksMass >= PastBlocksMin) {
                        if ((PastRateAdjustmentRatio <= EventHorizonDeviationSlow) || (PastRateAdjustmentRatio >= EventHorizonDeviationFast)) { assert(BlockReading); break; }
                }
                if (BlockReading->pprev == NULL) { assert(BlockReading); break; }
                BlockReading = BlockReading->pprev;
        }

        arith_uint256 bnNew(PastDifficultyAverage);

        if (PastRateActualSeconds != 0 && PastRateTargetSeconds != 0) {
            // LogPrintf("Difficulty Retarget - Kimoto Gravity Well\n");
            bnNew *= PastRateActualSeconds;
            bnNew /= PastRateTargetSeconds;
       }
        if (bnNew > bnPowLimit)
            bnNew = bnPowLimit;

/* debug print (commented out due to spamming logs when the loop above breaks)
   printf("Difficulty Retarget - Kimoto Gravity Well\n");
   printf("PastRateAdjustmentRatio = %g\n", PastRateAdjustmentRatio);
   printf("Before: %08x %s\n", BlockLastSolved->nBits, arith_uint256().SetCompact(BlockLastSolved->nBits).ToString().c_str());
   printf("After: %08x %s\n", bnNew.GetCompact(), bnNew.ToString().c_str());
*/

        return bnNew.GetCompact();
}

<|endoftext|>