<commit_before>// Gao Wang and Kushal K. Dey (c) 2016
#include <iostream>
#include <fstream>
#include <cstdio>
#include <ctime>
#include "pfa.hpp"

//! 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 omega [C, 1] initial weight of membership loadings, a discrete set corresponding to q
// @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 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 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

extern "C" int pfa_em(double *, double *, double *, double *, double *,
                      int *, int *, int *, int *, double *, int *, int *,
                      double *, double *, int *,
                      int *, int *, int *, int *, int *);

int pfa_em(double * X, double * F, double * P, double * q, double * omega,
           int * N, int * J, int * K, int * C, double * tol, int * maxiter, int * niter,
           double * loglik, double * L, int * status,
           int * logfn_1, int * nlf_1, int * logfn_2, int * nlf_2, int * n_threads) {
  //
  // Set up logfiles
  //
  bool keeplog = (*nlf_1 > 0) ? true : false;
  std::fstream f1;
  std::fstream f2;
  if (keeplog) {
    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';
    f1.open(f1_log, std::fstream::out);
    f2.open(f2_log, std::fstream::out);
    time_t now;
    time(&now);
    f1 << "#\n# " << asctime(localtime(&now)) << "#\n\n";
    f2 << "#\n# " << asctime(localtime(&now)) << "#\n\n";
    f1.close();
    f2.close();
    f1.open(f1_log, std::fstream::app);
    f2.open(f2_log, std::fstream::app);
  }
  //
  // Fit model via EM
  //
  *niter = 0;
  PFA model(X, F, P, q, omega, L, *N, *J, *K, *C);
  model.set_threads(*n_threads);
  model.print(f1, 0);
  while (*niter <= *maxiter) {
    if (keeplog) {
      f1 << "#----------------------------------\n";
      f1 << "# Iteration " << *niter << "\n";
      f1 << "#----------------------------------\n";
      model.print(f1, 1);
      f2 << "#----------------------------------\n";
      f2 << "# Iteration " << *niter << "\n";
      f2 << "#----------------------------------\n";
      model.print(f2, 2);
    }
    model.get_loglik_given_nkq();
    loglik[*niter] = model.get_loglik();
    (*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.update_LF();
    model.update_weights();
  }
  if (*status)
    std::cerr << "[WARNING] EM algorithm failed to converge after " << *niter << " iterations!" << std::endl;
  if (keeplog) {
    f1.close();
    f2.close();
  }
  return 0;
}
<commit_msg>Keep track of loglik in log files<commit_after>// Gao Wang and Kushal K. Dey (c) 2016
#include <iostream>
#include <fstream>
#include <cstdio>
#include <ctime>
#include "pfa.hpp"

//! 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 omega [C, 1] initial weight of membership loadings, a discrete set corresponding to q
// @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 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 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

extern "C" int pfa_em(double *, double *, double *, double *, double *,
                      int *, int *, int *, int *, double *, int *, int *,
                      double *, double *, int *,
                      int *, int *, int *, int *, int *);

int pfa_em(double * X, double * F, double * P, double * q, double * omega,
           int * N, int * J, int * K, int * C, double * tol, int * maxiter, int * niter,
           double * loglik, double * L, int * status,
           int * logfn_1, int * nlf_1, int * logfn_2, int * nlf_2, int * n_threads) {
  //
  // Set up logfiles
  //
  bool keeplog = (*nlf_1 > 0) ? true : false;
  std::fstream f1;
  std::fstream f2;
  if (keeplog) {
    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';
    f1.open(f1_log, std::fstream::out);
    f2.open(f2_log, std::fstream::out);
    time_t now;
    time(&now);
    f1 << "#\n# " << asctime(localtime(&now)) << "#\n\n";
    f2 << "#\n# " << asctime(localtime(&now)) << "#\n\n";
    f1.close();
    f2.close();
    f1.open(f1_log, std::fstream::app);
    f2.open(f2_log, std::fstream::app);
  }
  //
  // Fit model via EM
  //
  *niter = 0;
  PFA model(X, F, P, q, omega, L, *N, *J, *K, *C);
  model.set_threads(*n_threads);
  model.print(f1, 0);
  while (*niter <= *maxiter) {
    if (keeplog) {
      f1 << "#----------------------------------\n";
      f1 << "# Iteration " << *niter << "\n";
      f1 << "#----------------------------------\n";
      model.print(f1, 1);
      f2 << "#----------------------------------\n";
      f2 << "# Iteration " << *niter << "\n";
      f2 << "#----------------------------------\n";
      model.print(f2, 2);
    }
    model.get_loglik_given_nkq();
    loglik[*niter] = model.get_loglik();
    if (keeplog) {
      f1 << "Loglik:\t" << 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.update_LF();
    model.update_weights();
  }
  if (*status)
    std::cerr << "[WARNING] EM algorithm failed to converge after " << *niter << " iterations!" << std::endl;
  if (keeplog) {
    f1.close();
    f2.close();
  }
  return 0;
}
<|endoftext|>


<commit_before>///
/// @file  phi.cpp
/// @brief The PhiCache class calculates the partial sieve function
///        (a.k.a. Legendre-sum) using the recursive formula:
///        phi(x, a) = phi(x, a - 1) - phi(x / primes[a], a - 1).
///        phi(x, a) counts the numbers <= x that are not divisible by
///        any of the first a primes. The algorithm used is an
///        optimized version of the algorithm described in Tomás
///        Oliveira e Silva's paper [1]. I have added 5 optimizations
///        to my implementation which significantly speed up the
///        calculation:
///
///        * Calculate phi(x, a) in O(1) using formula [2] if a <= 6.
///        * Calculate phi(x, a) in O(1) using pi(x) lookup table if x < prime[a+1]^2.
///        * Cache results of phi(x, a) if x and a are small.
///        * Calculate all phi(x, a) = 1 upfront in O(1).
///        * Stop recursion at c instead of 1.
///
///       [1] Tomás Oliveira e Silva, Computing pi(x): the combinatorial
///           method, Revista do DETUA, vol. 4, no. 6, March 2006, p. 761.
///           http://sweet.ua.pt/tos/bib/5.4.pdf
///       [2] phi(x, a) = (x / pp) * φ(pp) + phi(x % pp, a)
///           with pp = 2 * 3 * ... * prime[a]
///
/// Copyright (C) 2021 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <PiTable.hpp>
#include <primecount-internal.hpp>
#include <primesieve.hpp>
#include <ModuloWheel.hpp>
#include <gourdon.hpp>
#include <fast_div.hpp>
#include <imath.hpp>
#include <min.hpp>
#include <PhiTiny.hpp>
#include <print.hpp>

#include <stdint.h>
#include <algorithm>
#include <array>
#include <vector>
#include <limits>

using namespace std;
using namespace primecount;

namespace {

class PhiCache
{
public:
  PhiCache(int64_t limit,
           const vector<int32_t>& primes,
           const PiTable& pi) :
    primes_(primes),
    pi_(pi)
  {
    // The cache limit has been tuned for both pi_legendre(x) and
    // pi_meissel(x) as these functions are frequently used in primecount.
    // The idea is to allocate only a small amount of cache memory for
    // tiny computations (because initializing a lot of cache memory is
    // slow). On the other hand, for large and long running computations
    // we use the maximum amount of cache memory.
    auto u16_max = numeric_limits<uint16_t>::max();
    cache_limit_ = (uint64_t) pow((double) limit, 1 / 2.5);
    cache_limit_ = min(cache_limit_, u16_max);
  }

  /// Calculate phi(x, a) using the recursive formula:
  /// phi(x, a) = phi(x, a - 1) - phi(x / primes[a], a - 1)
  ///
  template <int SIGN>
  int64_t phi(int64_t x, int64_t a)
  {
    if (x <= primes_[a])
      return SIGN;
    else if (is_phi_tiny(a))
      return phi_tiny(x, a) * SIGN;
    else if (is_pix(x, a))
      return (pi_[x] - a + 1) * SIGN;
    else if (is_cached(x, a))
      return phi_cache(x, a) * SIGN;

    int64_t sqrtx = isqrt(x);
    int64_t c = PhiTiny::get_c(sqrtx);
    int64_t sum = phi_tiny(x, c) * SIGN;
    int64_t i, xp;

    for (i = c; i < a; i++)
    {
      xp = fast_div(x, primes_[i + 1]);
      if (is_pix(xp, i) ||
          xp <= primes_[i])
        break;
      sum += phi<-SIGN>(xp, i);
    }

    for (; i < a; i++)
    {
      xp = fast_div(x, primes_[i + 1]);
      if (xp <= primes_[i])
        break;
      sum += (pi_[xp] - i + 1) * -SIGN;
    }

    // phi(x, a) = 1 for all primes[a] >= x
    sum += (a - i) * -SIGN;
    update_cache(x, a, sum);

    return sum;
  }

private:
  /// phi(x, a) counts the numbers <= x that are not divisible by any of
  /// the first a primes. If x < prime[a+1]^2 then phi(x, a) counts the
  /// number of primes <= x, minus the first a primes, plus the number 1.
  /// Hence if x < prime[a+1]^2: phi(x, a) = pi(x) - a + 1.
  ///
  bool is_pix(int64_t x, int64_t a) const
  {
    return x < pi_.size() &&
           x < isquare(primes_[a + 1]);
  }

  bool is_cached(uint64_t x, uint64_t a) const
  {
    x = ModuloWheel::to_index(x);
    return a < cache_.size() &&
           x < cache_[a].size() &&
           cache_[a][x] != 0;
  }

  int64_t phi_cache(uint64_t x, uint64_t a) const
  {
    x = ModuloWheel::to_index(x);
    return cache_[a][x];
  }

  void update_cache(uint64_t x, uint64_t a, int64_t sum)
  {
    // In order to increase the capacity of our phi cache we use a
    // modulo 2310 wheel that does not store any numbers that are
    // divisible by 2, 3, 5, 7 and 11. In a modulo 2310 wheel 480 array
    // items span an interval of size 2310. Hence by using a modulo
    // 2310 wheel we can increase our cache's capacity by 2310 / 480
    // = 4.8125 without increasing its memory usage.
    x = ModuloWheel::to_index(x);

    if (a >= cache_.size() ||
        x > cache_limit_)
      return;

    if (x >= cache_[a].size())
    {
      cache_[a].reserve(cache_limit_ + 1);
      cache_[a].resize(x + 1, 0);
    }

    sum = abs(sum);
    assert(sum <= numeric_limits<uint16_t>::max());
    assert(cache_[a][x] == 0);
    cache_[a][x] = (uint16_t) sum;
  }

  uint64_t cache_limit_ = 0;
  enum { MAX_A = 100 };
  array<vector<uint16_t>, MAX_A> cache_;
  const vector<int32_t>& primes_;
  const PiTable& pi_;
};

/// If a is very large (i.e. prime[a] > sqrt(x)) then we need to
/// calculate phi(x, a) using an alternative algorithm. First, because
/// in this case there actually exists a much faster algorithm. And
/// secondly, because storing the first a primes in a vector may use a
/// huge amount of memory and cause an out of memory error.
///
/// This alternative algorithm works if a >= pi(sqrt(x)). However, we
/// need to be very careful: phi_pix(x, a) may call pi_legendre(x) which
/// calls phi(x, a) with a = pi(sqrt(x)), which would then again call
/// phi_pix(x, a) thereby causing infinite recursion. In order to prevent
/// this issue this function must only be called with a > pi(sqrt(x)).
///
int64_t phi_pix(int64_t x, int64_t a, int threads)
{
  bool print = is_print();
  set_print(false);

  int64_t pix = pi(x, threads);
  int64_t sum;

  if (a <= pix)
    sum = pix - a + 1;
  else
    sum = 1;

  set_print(print);
  return sum;
}

} // namespace

namespace primecount {

/// Partial sieve function (a.k.a. Legendre-sum).
/// phi(x, a) counts the numbers <= x that are not divisible
/// by any of the first a primes.
///
int64_t phi(int64_t x, int64_t a, int threads)
{
  if (x < 1) return 0;
  if (a > x) return 1;
  if (a < 1) return x;

  if (is_phi_tiny(a))
    return phi_tiny(x, a);

  int64_t sqrtx = isqrt(x);
  if (a > sqrtx)
    return phi_pix(x, a, threads);

  // We use 1 indexing i.e. primes[1] = 2
  vector<int32_t> primes;
  primes.reserve(a + 2);
  primes.push_back(0);
  primesieve::iterator it;

  // Store the first a primes in a vector
  for (int64_t i = 0; i < a; i++)
  {
    int64_t prime = it.next_prime();
    primes.push_back((int32_t) prime);
    if (prime >= x)
      return 1;
    // We use if (prime > sqrtx) here instead of (prime >= sqrtx) because
    // we want to prevent that our pi_legendre(x) uses this code path.
    // Otherwise pi_legendre(x) would switch to using pi_gourdon(x) under
    // the hood which is not what users expect. Also using (prime >= sqrtx)
    // here would cause infinite recursion, more info at phi_pix(x, a).
    if (prime > sqrtx)
      return phi_pix(x, a, threads);
  }

  // Use a large pi(x) lookup table for speed
  int64_t c = PhiTiny::get_c(sqrtx);
  PiTable pi(max(sqrtx, primes[a]), threads);
  int64_t pi_sqrtx = min(pi[sqrtx], a);
  int64_t sum = phi_tiny(x, c) - a + pi_sqrtx;
  int64_t thread_threshold = (int64_t) 1e10;
  threads = ideal_num_threads(threads, x, thread_threshold);

  #pragma omp parallel num_threads(threads) reduction(+: sum)
  {
    // Each thread uses its own PhiCache object in
    // order to avoid thread synchronization.
    PhiCache cache(x, primes, pi);

    #pragma omp for nowait schedule(dynamic, 16)
    for (int64_t i = c; i < pi_sqrtx; i++)
      sum += cache.phi<-1>(x / primes[i + 1], i);
  }

  return sum;
}

/// The default phi(x, a) implementation does not print anything to the
/// screen as it is used by pi_simple(x) which is used all over the
/// place (e.g. to initialize S1, S2, P2, P3, ...) and we don't want to
/// print any info about this. Hence we also provide phi_print(x, a) for
/// use cases where we do want to print the result of phi(x, a).
///
int64_t phi_print(int64_t x, int64_t a, int threads)
{
  print("");
  print("=== phi(x, a) ===");

  double time = get_time();
  int64_t sum = phi(x, a, threads);
  print("phi", sum, time);

  return sum;
}

} // namespace
<commit_msg>Accurate phi(x, a) by pi(x) detection<commit_after>///
/// @file  phi.cpp
/// @brief The PhiCache class calculates the partial sieve function
///        (a.k.a. Legendre-sum) using the recursive formula:
///        phi(x, a) = phi(x, a - 1) - phi(x / primes[a], a - 1).
///        phi(x, a) counts the numbers <= x that are not divisible by
///        any of the first a primes. The algorithm used is an
///        optimized version of the algorithm described in Tomás
///        Oliveira e Silva's paper [1]. I have added 5 optimizations
///        to my implementation which significantly speed up the
///        calculation:
///
///        * Calculate phi(x, a) in O(1) using formula [2] if a <= 6.
///        * Calculate phi(x, a) in O(1) using pi(x) lookup table if x < prime[a+1]^2.
///        * Cache results of phi(x, a) if x and a are small.
///        * Calculate all phi(x, a) = 1 upfront in O(1).
///        * Stop recursion at c instead of 1.
///
///       [1] Tomás Oliveira e Silva, Computing pi(x): the combinatorial
///           method, Revista do DETUA, vol. 4, no. 6, March 2006, p. 761.
///           http://sweet.ua.pt/tos/bib/5.4.pdf
///       [2] phi(x, a) = (x / pp) * φ(pp) + phi(x % pp, a)
///           with pp = 2 * 3 * ... * prime[a]
///
/// Copyright (C) 2021 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <PiTable.hpp>
#include <primecount-internal.hpp>
#include <generate.hpp>
#include <gourdon.hpp>
#include <fast_div.hpp>
#include <imath.hpp>
#include <min.hpp>
#include <ModuloWheel.hpp>
#include <PhiTiny.hpp>
#include <print.hpp>

#include <stdint.h>
#include <algorithm>
#include <array>
#include <vector>
#include <limits>

using namespace std;
using namespace primecount;

namespace {

class PhiCache
{
public:
  PhiCache(int64_t limit,
           const vector<int32_t>& primes,
           const PiTable& pi) :
    primes_(primes),
    pi_(pi)
  {
    // The cache limit has been tuned for both pi_legendre(x) and
    // pi_meissel(x) as these functions are frequently used in primecount.
    // The idea is to allocate only a small amount of cache memory for
    // tiny computations (because initializing a lot of cache memory is
    // slow). On the other hand, for large and long running computations
    // we use the maximum amount of cache memory.
    auto u16_max = numeric_limits<uint16_t>::max();
    cache_limit_ = (uint64_t) pow((double) limit, 1 / 2.5);
    cache_limit_ = min(cache_limit_, u16_max);
  }

  /// Calculate phi(x, a) using the recursive formula:
  /// phi(x, a) = phi(x, a - 1) - phi(x / primes[a], a - 1)
  ///
  template <int SIGN>
  int64_t phi(int64_t x, int64_t a)
  {
    if (x <= primes_[a])
      return SIGN;
    else if (is_phi_tiny(a))
      return phi_tiny(x, a) * SIGN;
    else if (is_pix(x, a))
      return (pi_[x] - a + 1) * SIGN;
    else if (is_cached(x, a))
      return phi_cache(x, a) * SIGN;

    int64_t sqrtx = isqrt(x);
    int64_t c = PhiTiny::get_c(sqrtx);
    int64_t sum = phi_tiny(x, c) * SIGN;
    int64_t i, xp;

    for (i = c; i < a; i++)
    {
      xp = fast_div(x, primes_[i + 1]);
      if (is_pix(xp, i) ||
          xp <= primes_[i])
        break;
      sum += phi<-SIGN>(xp, i);
    }

    for (; i < a; i++)
    {
      xp = fast_div(x, primes_[i + 1]);
      if (xp <= primes_[i])
        break;
      sum += (pi_[xp] - i + 1) * -SIGN;
    }

    // phi(x, a) = 1 for all primes[a] >= x
    sum += (a - i) * -SIGN;
    update_cache(x, a, sum);

    return sum;
  }

private:
  /// phi(x, a) counts the numbers <= x that are not divisible by any of
  /// the first a primes. If x < prime[a+1]^2 then phi(x, a) counts the
  /// number of primes <= x, minus the first a primes, plus the number 1.
  /// Hence if x < prime[a+1]^2: phi(x, a) = pi(x) - a + 1.
  ///
  bool is_pix(int64_t x, int64_t a) const
  {
    return x < pi_.size() &&
           x < isquare(primes_[a + 1]);
  }

  bool is_cached(uint64_t x, uint64_t a) const
  {
    x = ModuloWheel::to_index(x);
    return a < cache_.size() &&
           x < cache_[a].size() &&
           cache_[a][x] != 0;
  }

  int64_t phi_cache(uint64_t x, uint64_t a) const
  {
    x = ModuloWheel::to_index(x);
    return cache_[a][x];
  }

  void update_cache(uint64_t x, uint64_t a, int64_t sum)
  {
    // In order to increase the capacity of our phi cache we use a
    // modulo 2310 wheel that does not store any numbers that are
    // divisible by 2, 3, 5, 7 and 11. In a modulo 2310 wheel 480 array
    // items span an interval of size 2310. Hence by using a modulo
    // 2310 wheel we can increase our cache's capacity by 2310 / 480
    // = 4.8125 without increasing its memory usage.
    x = ModuloWheel::to_index(x);

    if (a >= cache_.size() ||
        x > cache_limit_)
      return;

    if (x >= cache_[a].size())
    {
      cache_[a].reserve(cache_limit_ + 1);
      cache_[a].resize(x + 1, 0);
    }

    sum = abs(sum);
    assert(sum <= numeric_limits<uint16_t>::max());
    assert(cache_[a][x] == 0);
    cache_[a][x] = (uint16_t) sum;
  }

  uint64_t cache_limit_ = 0;
  enum { MAX_A = 100 };
  array<vector<uint16_t>, MAX_A> cache_;
  const vector<int32_t>& primes_;
  const PiTable& pi_;
};

/// If a is very large (i.e. prime[a] > sqrt(x)) then we need to
/// calculate phi(x, a) using an alternative algorithm. First, because
/// in this case there actually exists a much faster algorithm. And
/// secondly, because storing the first a primes in a vector may use a
/// huge amount of memory and cause an out of memory error.
///
/// This alternative algorithm works if a >= pi(sqrt(x)). However, we
/// need to be very careful: phi_pix(x, a) may call pi_legendre(x) which
/// calls phi(x, a) with a = pi(sqrt(x)), which would then again call
/// phi_pix(x, a) thereby causing infinite recursion. In order to prevent
/// this issue this function must only be called with a > pi(sqrt(x)).
///
int64_t phi_pix(int64_t x, int64_t a, int threads)
{
  bool print = is_print();
  set_print(false);

  int64_t pix = pi(x, threads);
  int64_t sum;

  if (a <= pix)
    sum = pix - a + 1;
  else
    sum = 1;

  set_print(print);
  return sum;
}

} // namespace

namespace primecount {

/// Partial sieve function (a.k.a. Legendre-sum).
/// phi(x, a) counts the numbers <= x that are not divisible
/// by any of the first a primes.
///
int64_t phi(int64_t x, int64_t a, int threads)
{
  if (x < 1) return 0;
  if (a > x) return 1;
  if (a < 1) return x;

  if (is_phi_tiny(a))
    return phi_tiny(x, a);

  // Use a large pi(x) lookup table for speed
  int64_t sqrtx = isqrt(x);
  PiTable pi(sqrtx, threads);
  int64_t pi_sqrtx = pi[sqrtx];

  // We use if (a > pi(sqrt(x)) here instead of (a >= pi(sqrt(x)) because
  // we want to prevent that our pi_legendre(x) uses this code path.
  // Otherwise pi_legendre(x) would switch to using pi_gourdon(x) under
  // the hood which is not what users expect. Also using (a >= pi(sqrt(x))
  // here would cause infinite recursion, more info at phi_pix(x, a).
  if (a > pi_sqrtx)
    return phi_pix(x, a, threads);

  auto primes = generate_n_primes<int32_t>(a);
  int64_t c = PhiTiny::get_c(sqrtx);
  pi_sqrtx = min(a, pi_sqrtx);
  int64_t sum = phi_tiny(x, c) - a + pi_sqrtx;
  int64_t thread_threshold = (int64_t) 1e10;
  threads = ideal_num_threads(threads, x, thread_threshold);

  #pragma omp parallel num_threads(threads) reduction(+: sum)
  {
    // Each thread uses its own PhiCache object in
    // order to avoid thread synchronization.
    PhiCache cache(x, primes, pi);

    #pragma omp for nowait schedule(dynamic, 16)
    for (int64_t i = c; i < pi_sqrtx; i++)
      sum += cache.phi<-1>(x / primes[i + 1], i);
  }

  return sum;
}

/// The default phi(x, a) implementation does not print anything to the
/// screen as it is used by pi_simple(x) which is used all over the
/// place (e.g. to initialize S1, S2, P2, P3, ...) and we don't want to
/// print any info about this. Hence we also provide phi_print(x, a) for
/// use cases where we do want to print the result of phi(x, a).
///
int64_t phi_print(int64_t x, int64_t a, int threads)
{
  print("");
  print("=== phi(x, a) ===");

  double time = get_time();
  int64_t sum = phi(x, a, threads);
  print("phi", sum, time);

  return sum;
}

} // namespace
<|endoftext|>


<commit_before>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2015 The Syscoin Core developers
// 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 "chainparamsbase.h"

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

    // Genesis block
    if (pindexLast == NULL)
        return nProofOfWorkLimit;
	// SYSCOIN set difficulty to about 1040 at block 1k to avoid local miners mining all the blocks
 	std::string chain = ChainNameFromCommandLine();
 	if((pindexLast->nHeight+1) == 1000 && chain == CBaseChainParams::MAIN)
 		return 0x1d00003f;
    // Only change once per difficulty adjustment 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;
    }
    // SYSCOIN 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
    int nHeightFirst = pindexLast->nHeight - blockstogoback;
    assert(nHeightFirst >= 0);
    const CBlockIndex* pindexFirst = pindexLast->GetAncestor(nHeightFirst);
    assert(pindexFirst);

    return CalculateNextWorkRequired(pindexLast, pindexFirst->GetBlockTime(), params);
}
// SYSCOIN DGW diff algo
unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params& params)
{
    if (params.fPowNoRetargeting)
        return pindexLast->nBits;

	/* current difficulty formula, dash - DarkGravity v3, written by Evan Duffield - evan@dashpay.io */
    const CBlockIndex *BlockLastSolved = pindexLast;
    const CBlockIndex *BlockReading = pindexLast;
    int64_t nActualTimespan = 0;
    int64_t LastBlockTime = 0;
    int64_t PastBlocksMin = 24;
    int64_t PastBlocksMax = 24;
    int64_t CountBlocks = 0;
    uint256 PastDifficultyAverage;
    uint256 PastDifficultyAveragePrev;

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

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

        if(CountBlocks <= PastBlocksMin) {
            if (CountBlocks == 1) { PastDifficultyAverage.SetCompact(BlockReading->nBits); }
            else { PastDifficultyAverage = ((PastDifficultyAveragePrev * CountBlocks) + (uint256().SetCompact(BlockReading->nBits))) / (CountBlocks + 1); }
            PastDifficultyAveragePrev = PastDifficultyAverage;
        }

        if(LastBlockTime > 0){
            int64_t Diff = (LastBlockTime - BlockReading->GetBlockTime());
            nActualTimespan += Diff;
        }
        LastBlockTime = BlockReading->GetBlockTime();

        if (BlockReading->pprev == NULL) { assert(BlockReading); break; }
        BlockReading = BlockReading->pprev;
    }

    uint256 bnNew(PastDifficultyAverage);

    int64_t _nTargetTimespan = CountBlocks * Params().GetConsensus().nPowTargetSpacing;

    if (nActualTimespan < _nTargetTimespan/3)
        nActualTimespan = _nTargetTimespan/3;
    if (nActualTimespan > _nTargetTimespan*3)
        nActualTimespan = _nTargetTimespan*3;

    // Retarget
    bnNew *= nActualTimespan;
    bnNew /= _nTargetTimespan;

    if (bnNew > Params().ProofOfWorkLimit()){
        bnNew = Params().ProofOfWorkLimit();
    }

    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 error("CheckProofOfWork(): nBits below minimum work");

    // Check proof of work matches claimed amount
	std::string chain = ChainNameFromCommandLine();
    if (UintToArith256(hash) > bnTarget)
        return error("CheckProofOfWork(): hash doesn't match nBits");

    return true;
}

arith_uint256 GetBlockProof(const CBlockIndex& block)
{
    arith_uint256 bnTarget;
    bool fNegative;
    bool fOverflow;
    bnTarget.SetCompact(block.nBits, &fNegative, &fOverflow);
    if (fNegative || fOverflow || bnTarget == 0)
        return 0;
    // We need to compute 2**256 / (bnTarget+1), but we can't represent 2**256
    // as it's too large for a arith_uint256. However, as 2**256 is at least as large
    // as bnTarget+1, it is equal to ((2**256 - bnTarget - 1) / (bnTarget+1)) + 1,
    // or ~bnTarget / (nTarget+1) + 1.
    return (~bnTarget / (bnTarget + 1)) + 1;
}

int64_t GetBlockProofEquivalentTime(const CBlockIndex& to, const CBlockIndex& from, const CBlockIndex& tip, const Consensus::Params& params)
{
    arith_uint256 r;
    int sign = 1;
    if (to.nChainWork > from.nChainWork) {
        r = to.nChainWork - from.nChainWork;
    } else {
        r = from.nChainWork - to.nChainWork;
        sign = -1;
    }
    r = r * arith_uint256(params.nPowTargetSpacing) / GetBlockProof(tip);
    if (r.bits() > 63) {
        return sign * std::numeric_limits<int64_t>::max();
    }
    return sign * r.GetLow64();
}
<commit_msg>compile<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2015 The Syscoin Core developers
// 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 "chainparamsbase.h"

unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params)
{
	return CalculateNextWorkRequired(indexLast, params);
}
// SYSCOIN DGW diff algo
unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, const Consensus::Params& params)
{

	/* current difficulty formula, dash - DarkGravity v3, written by Evan Duffield - evan@dashpay.io */
    // Genesis block
    if (pindexLast == NULL)
        return nProofOfWorkLimit;
    if (params.fPowNoRetargeting)
        return pindexLast->nBits;

	const arith_uint256 nProofOfWorkLimit = UintToArith256(params.powLimit);
    const CBlockIndex *BlockLastSolved = pindexLast;
    const CBlockIndex *BlockReading = pindexLast;
    int64_t nActualTimespan = 0;
    int64_t LastBlockTime = 0;
    int64_t PastBlocksMin = 24;
    int64_t PastBlocksMax = 24;
    int64_t CountBlocks = 0;
    arith_uint256 PastDifficultyAverage;
    arith_uint256 PastDifficultyAveragePrev;

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

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

        if(CountBlocks <= PastBlocksMin) {
            if (CountBlocks == 1) { PastDifficultyAverage.SetCompact(BlockReading->nBits); }
            else { PastDifficultyAverage = ((PastDifficultyAveragePrev * CountBlocks) + (arith_uint256().SetCompact(BlockReading->nBits))) / (CountBlocks + 1); }
            PastDifficultyAveragePrev = PastDifficultyAverage;
        }

        if(LastBlockTime > 0){
            int64_t Diff = (LastBlockTime - BlockReading->GetBlockTime());
            nActualTimespan += Diff;
        }
        LastBlockTime = BlockReading->GetBlockTime();

        if (BlockReading->pprev == NULL) { assert(BlockReading); break; }
        BlockReading = BlockReading->pprev;
    }

    arith_uint256 bnNew(PastDifficultyAverage);

    int64_t _nTargetTimespan = CountBlocks * Params().GetConsensus().nPowTargetSpacing;

    if (nActualTimespan < _nTargetTimespan/3)
        nActualTimespan = _nTargetTimespan/3;
    if (nActualTimespan > _nTargetTimespan*3)
        nActualTimespan = _nTargetTimespan*3;

    // Retarget
    bnNew *= nActualTimespan;
    bnNew /= _nTargetTimespan;

    if (bnNew > nProofOfWorkLimit)){
        bnNew = nProofOfWorkLimit;
    }

    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 error("CheckProofOfWork(): nBits below minimum work");

    // Check proof of work matches claimed amount
	std::string chain = ChainNameFromCommandLine();
    if (UintToArith256(hash) > bnTarget)
        return error("CheckProofOfWork(): hash doesn't match nBits");

    return true;
}

arith_uint256 GetBlockProof(const CBlockIndex& block)
{
    arith_uint256 bnTarget;
    bool fNegative;
    bool fOverflow;
    bnTarget.SetCompact(block.nBits, &fNegative, &fOverflow);
    if (fNegative || fOverflow || bnTarget == 0)
        return 0;
    // We need to compute 2**256 / (bnTarget+1), but we can't represent 2**256
    // as it's too large for a arith_uint256. However, as 2**256 is at least as large
    // as bnTarget+1, it is equal to ((2**256 - bnTarget - 1) / (bnTarget+1)) + 1,
    // or ~bnTarget / (nTarget+1) + 1.
    return (~bnTarget / (bnTarget + 1)) + 1;
}

int64_t GetBlockProofEquivalentTime(const CBlockIndex& to, const CBlockIndex& from, const CBlockIndex& tip, const Consensus::Params& params)
{
    arith_uint256 r;
    int sign = 1;
    if (to.nChainWork > from.nChainWork) {
        r = to.nChainWork - from.nChainWork;
    } else {
        r = from.nChainWork - to.nChainWork;
        sign = -1;
    }
    r = r * arith_uint256(params.nPowTargetSpacing) / GetBlockProof(tip);
    if (r.bits() > 63) {
        return sign * std::numeric_limits<int64_t>::max();
    }
    return sign * r.GetLow64();
}
<|endoftext|>


<commit_before>#include "stdio.h"
#include "stdlib.h"

#include "iRRAM/core.h"

#if ($iRRAM_BACKEND == MPFR)
	#include "MPFR_ext.h"
#else
	#include "Currently no additional backend!"
#endif

namespace iRRAM {

REAL root_approx(int prec, const REAL& x,int n) {
   int u=upperbound(x)/n;
   REAL error;
   if (u < prec) return 0;
   REAL r=scale(REAL(1),u);
   REAL r_2=x/power(r,n-1);
   do {
      r+=(r_2-r)/n;
      r_2=x/power(r,n-1);
      error=r - r_2;
   } while ( !bound(error,prec) );
   return r;
};

REAL root(const REAL& x,int n) {
   return limit(root_approx,x,n);
}

#ifdef OLDSQRT
#ifdef MP_mv_sqrt

  REAL MP_sqrt_approx (int prec, const REAL& x){
    DYADIC xd=approx(x,prec-1);
    MP_mv_sqrt(xd.value,xd.value,prec-1);
    return REAL(xd);
  };
  #define SQRT_APPROX MP_sqrt_approx

#else

  REAL gen_sqrt_approx(int k,const REAL& x){
    REAL a=1,b=x/a;
    do {
       a=(a+b)/2;
       b=x/a;
    } while ( !bound(a-b,k) );
    return a;
  }
  #define SQRT_APPROX gen_sqrt_approx

#endif

REAL sqrt_approx (int prec, const REAL& x){
  if (bound(x, 2*prec) ) return 0;
  int s2=size(x)/2;
  REAL y=scale(x,-s2*2);
  y=lipschitz(SQRT_APPROX,2,prec-s2,y);
  y=scale(y,s2);
  return y;
};

REAL sqrt (const REAL& x){
 return limit(sqrt_approx,x);
};
#else

#ifdef MP_mv_sqrt

  REAL sqrt(const REAL& x){
  if (!x.value) (const_cast<REAL&>(x)).mp_make_mp();
  MP_type zvalue;
  sizetype zerror,xsize,proderror;
  int local_prec;
  x.getsize(xsize);
  sizetype_shift(zerror,x.error,2);
  if (sizetype_less(xsize,zerror)) {
    MP_init(zvalue);
    MP_int_to_mp(0,zvalue);
    sizetype_sqrt(zerror,x.error);
    sizetype_shift(zerror,zerror,1);
    return REAL(zvalue,zerror);
  }
  sizetype_dec(xsize,x.error);
  sizetype_sqrt(proderror,xsize);
  sizetype_div(zerror,x.error,proderror);
  sizetype_half(zerror,zerror);
  if (ACTUAL_STACK.prec_policy == 0)
    local_prec=max(ACTUAL_STACK.actual_prec,zerror.exponent);
  else
    local_prec=max(xsize.exponent+ACTUAL_STACK.actual_prec,zerror.exponent);
  MP_init(zvalue);
  MP_mv_sqrt(x.value,zvalue,local_prec);
  sizetype_inc_one(zerror,local_prec);
//printf("%d*2^%d\n",zerror.mantissa,zerror.exponent);
  return REAL(zvalue,zerror);
};

#else

  REAL gen_sqrt_approx(int k,const REAL& x){
    REAL a=1,b=x/a;
    do {
       a=(a+b)/2;
       b=x/a;
    } while ( !bound(a-b,k) );
    return a;
  }
  #define SQRT_APPROX gen_sqrt_approx

REAL sqrt_approx (int prec, const REAL& x){
  if (bound(x, 2*prec) ) return 0;
  int s2=size(x)/2;
  REAL y=scale(x,-s2*2);
  y=lipschitz(SQRT_APPROX,2,prec-s2,y);
  return scale(y,s2);
};

REAL sqrt (const REAL& x){
 return limit(sqrt_approx,x);
};
#endif

} // namespace iRRAM

#endif

<commit_msg>-Wpedantic: removed unneeded ";<commit_after>#include "stdio.h"
#include "stdlib.h"

#include "iRRAM/core.h"

#if ($iRRAM_BACKEND == MPFR)
	#include "MPFR_ext.h"
#else
	#include "Currently no additional backend!"
#endif

namespace iRRAM {

REAL root_approx(int prec, const REAL& x,int n) {
   int u=upperbound(x)/n;
   REAL error;
   if (u < prec) return 0;
   REAL r=scale(REAL(1),u);
   REAL r_2=x/power(r,n-1);
   do {
      r+=(r_2-r)/n;
      r_2=x/power(r,n-1);
      error=r - r_2;
   } while ( !bound(error,prec) );
   return r;
}

REAL root(const REAL& x,int n) {
   return limit(root_approx,x,n);
}

#ifdef OLDSQRT
#ifdef MP_mv_sqrt

  REAL MP_sqrt_approx (int prec, const REAL& x){
    DYADIC xd=approx(x,prec-1);
    MP_mv_sqrt(xd.value,xd.value,prec-1);
    return REAL(xd);
  };
  #define SQRT_APPROX MP_sqrt_approx

#else

  REAL gen_sqrt_approx(int k,const REAL& x){
    REAL a=1,b=x/a;
    do {
       a=(a+b)/2;
       b=x/a;
    } while ( !bound(a-b,k) );
    return a;
  }
  #define SQRT_APPROX gen_sqrt_approx

#endif

REAL sqrt_approx (int prec, const REAL& x){
  if (bound(x, 2*prec) ) return 0;
  int s2=size(x)/2;
  REAL y=scale(x,-s2*2);
  y=lipschitz(SQRT_APPROX,2,prec-s2,y);
  y=scale(y,s2);
  return y;
}

REAL sqrt (const REAL& x){
 return limit(sqrt_approx,x);
}
#else

#ifdef MP_mv_sqrt

  REAL sqrt(const REAL& x){
  if (!x.value) (const_cast<REAL&>(x)).mp_make_mp();
  MP_type zvalue;
  sizetype zerror,xsize,proderror;
  int local_prec;
  x.getsize(xsize);
  sizetype_shift(zerror,x.error,2);
  if (sizetype_less(xsize,zerror)) {
    MP_init(zvalue);
    MP_int_to_mp(0,zvalue);
    sizetype_sqrt(zerror,x.error);
    sizetype_shift(zerror,zerror,1);
    return REAL(zvalue,zerror);
  }
  sizetype_dec(xsize,x.error);
  sizetype_sqrt(proderror,xsize);
  sizetype_div(zerror,x.error,proderror);
  sizetype_half(zerror,zerror);
  if (ACTUAL_STACK.prec_policy == 0)
    local_prec=max(ACTUAL_STACK.actual_prec,zerror.exponent);
  else
    local_prec=max(xsize.exponent+ACTUAL_STACK.actual_prec,zerror.exponent);
  MP_init(zvalue);
  MP_mv_sqrt(x.value,zvalue,local_prec);
  sizetype_inc_one(zerror,local_prec);
//printf("%d*2^%d\n",zerror.mantissa,zerror.exponent);
  return REAL(zvalue,zerror);
}

#else

  REAL gen_sqrt_approx(int k,const REAL& x){
    REAL a=1,b=x/a;
    do {
       a=(a+b)/2;
       b=x/a;
    } while ( !bound(a-b,k) );
    return a;
  }
  #define SQRT_APPROX gen_sqrt_approx

REAL sqrt_approx (int prec, const REAL& x){
  if (bound(x, 2*prec) ) return 0;
  int s2=size(x)/2;
  REAL y=scale(x,-s2*2);
  y=lipschitz(SQRT_APPROX,2,prec-s2,y);
  return scale(y,s2);
}

REAL sqrt (const REAL& x){
 return limit(sqrt_approx,x);
}
#endif

} // namespace iRRAM

#endif

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015, Lakshman Anumolu, Pradeep Garigipati
 * All rights reserved.
 *
 * This file is part of MeshIO whose distribution is governed by
 * the BSD 2-Clause License contained in the accompanying LICENSE.txt
 * file.
 */

#ifndef __STL_HPP__
#define __STL_HPP__

#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include <sstream>
#include <cstdint>
#include "meshio_defines.hpp"

namespace meshio
{
namespace stl
{

template<typename T>
bool readAsciiSTL(std::vector< STLData<T> > &pObjects, const char* pFileName);

/*
 * Reads binary STL file assuming the format as described in
 * https://en.wikipedia.org/wiki/STL_(file_format). After the end of first
 * object, we assume that the next object's information starts with number of
 * triangles and the format continues.
 */
template<typename T>
bool readBinarySTL(std::vector< STLData<T> > &pObjects, const char* pFileName);

template<typename T=float>
bool readSTL(std::vector< STLData<T> > &pObjects, const char* pFileName)
{
    for(unsigned int i = 0; i < pObjects.size(); ++i)
        pObjects[i].clear();

    std::stringstream strErr;
    std::ifstream ifs(pFileName);
    if(!ifs) {
        strErr << "Cannot open file (" << pFileName << ")" << std::endl;
        std::cout << strErr.str() << std::endl;
        return false;
    }

    int bufferMaxSize = 80; // Only to read header
    char buffer[bufferMaxSize];

    ifs.getline(&buffer[0], bufferMaxSize);
    std::string line(&buffer[0]);
    ifs.close();

    if(line.substr(0,5) == "solid")
        return readAsciiSTL<T>(pObjects, pFileName);
    else
        return readBinarySTL<T>(pObjects, pFileName);
}

template<typename T=float>
bool readAsciiSTL(std::vector< STLData<T> > &pObjects, const char* pFileName)
{
    std::cout << "Reading Ascii STL file" << std::endl;
    return true;
}

template<typename T=float>
bool readBinarySTL(std::vector< STLData<T> > &pObjects, const char* pFileName)
{
    typedef float T2;
    std::cout << "Reading Binary STL file" << std::endl;

    uint32_t numTriangles;
    uint16_t attribByteCount;
    T2 value;
    std::vector<T2> values;
    std::size_t sizeT2 = sizeof(T2);
    std::size_t sizeUInt16 = sizeof(uint16_t);
    unsigned objectCount = 0;

    std::stringstream strErr;
    std::ifstream ifs(pFileName, std::ios::binary | std::ios::in);
    if(!ifs) {
        strErr << "Cannot open file (" << pFileName << ")" << std::endl;
        std::cout << strErr.str() << std::endl;
        return false;
    }

    char header[80];
    ifs.read(&header[0],80);

    ifs.read((char *)&numTriangles, sizeof(uint32_t));

    while(numTriangles) {
        std::cout<<"\tReading " << numTriangles << " facets from object "
            << ++objectCount << std::endl;
        STLData<T> stlObject;
        stlObject.resize(numTriangles);
        Vec4<T> position;
        Vec3<T2> normal;

        // Default assignment
        position.w = (T)1.;

        for(uint32_t facet = 0; facet < numTriangles; ++facet) {
            values.clear();
            for(short i = 0; i < 3; ++i) {
                ifs.read((char *)&value, sizeT2);
                values.push_back(value);
            }
            normal.x = values[0];
            normal.y = values[1];
            normal.z = values[2];
            stlObject.mNormals[facet] = normal;

            for(short i = 0; i < 3; ++i) {
                values.clear();
                for(short j = 0; j < 3; ++j) {
                    ifs.read((char *)&value, sizeT2);
                    values.push_back(value);
                }
                position.x = values[0];
                position.y = values[1];
                position.z = values[2];
                stlObject.mPositions[(3*facet)+i] = position;
            }

            ifs.read((char *)&attribByteCount, sizeUInt16);
        }
        pObjects.push_back(stlObject);
        stlObject.clear();

        numTriangles = 0;
        ifs.read((char *)&numTriangles, sizeof(uint32_t));
    }

    ifs.close();

    return true;
}

}
}

#endif // __STL_HPP__
<commit_msg>Make type float explicit in readBinarySTL<commit_after>/*
 * Copyright (c) 2015, Lakshman Anumolu, Pradeep Garigipati
 * All rights reserved.
 *
 * This file is part of MeshIO whose distribution is governed by
 * the BSD 2-Clause License contained in the accompanying LICENSE.txt
 * file.
 */

#ifndef __STL_HPP__
#define __STL_HPP__

#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include <sstream>
#include <cstdint>
#include "meshio_defines.hpp"

namespace meshio
{
namespace stl
{

template<typename T>
bool readAsciiSTL(std::vector< STLData<T> > &pObjects, const char* pFileName);

/*
 * Reads binary STL file assuming the format as described in
 * https://en.wikipedia.org/wiki/STL_(file_format). After the end of first
 * object, we assume that the next object's information starts with number of
 * triangles and the format continues.
 */
template<typename T>
bool readBinarySTL(std::vector< STLData<T> > &pObjects, const char* pFileName);

template<typename T=float>
bool readSTL(std::vector< STLData<T> > &pObjects, const char* pFileName)
{
    for(unsigned int i = 0; i < pObjects.size(); ++i)
        pObjects[i].clear();

    std::stringstream strErr;
    std::ifstream ifs(pFileName);
    if(!ifs) {
        strErr << "Cannot open file (" << pFileName << ")" << std::endl;
        std::cout << strErr.str() << std::endl;
        return false;
    }

    int bufferMaxSize = 80; // Only to read header
    char buffer[bufferMaxSize];

    ifs.getline(&buffer[0], bufferMaxSize);
    std::string line(&buffer[0]);
    ifs.close();

    if(line.substr(0,5) == "solid")
        return readAsciiSTL<T>(pObjects, pFileName);
    else
        return readBinarySTL<T>(pObjects, pFileName);
}

template<typename T=float>
bool readAsciiSTL(std::vector< STLData<T> > &pObjects, const char* pFileName)
{
    std::cout << "Reading Ascii STL file" << std::endl;
    return true;
}

template<typename T=float>
bool readBinarySTL(std::vector< STLData<T> > &pObjects, const char* pFileName)
{
    std::cout << "Reading Binary STL file" << std::endl;

    uint32_t numTriangles;
    uint16_t attribByteCount;
    float value;
    std::vector<float> values;
    std::size_t sizeT2 = sizeof(float);
    std::size_t sizeUInt16 = sizeof(uint16_t);
    unsigned objectCount = 0;

    std::stringstream strErr;
    std::ifstream ifs(pFileName, std::ios::binary | std::ios::in);
    if(!ifs) {
        strErr << "Cannot open file (" << pFileName << ")" << std::endl;
        std::cout << strErr.str() << std::endl;
        return false;
    }

    char header[80];
    ifs.read(&header[0],80);

    ifs.read((char *)&numTriangles, sizeof(uint32_t));

    while(numTriangles) {
        std::cout<<"\tReading " << numTriangles << " facets from object "
            << ++objectCount << std::endl;
        STLData<T> stlObject;
        stlObject.resize(numTriangles);
        Vec4<T> position;
        Vec3<float> normal;

        // Default assignment
        position.w = (T)1.;

        for(uint32_t facet = 0; facet < numTriangles; ++facet) {
            values.clear();
            for(short i = 0; i < 3; ++i) {
                ifs.read((char *)&value, sizeT2);
                values.push_back(value);
            }
            normal.x = values[0];
            normal.y = values[1];
            normal.z = values[2];
            stlObject.mNormals[facet] = normal;

            for(short i = 0; i < 3; ++i) {
                values.clear();
                for(short j = 0; j < 3; ++j) {
                    ifs.read((char *)&value, sizeT2);
                    values.push_back(value);
                }
                position.x = values[0];
                position.y = values[1];
                position.z = values[2];
                stlObject.mPositions[(3*facet)+i] = position;
            }

            ifs.read((char *)&attribByteCount, sizeUInt16);
        }
        pObjects.push_back(stlObject);
        stlObject.clear();

        numTriangles = 0;
        ifs.read((char *)&numTriangles, sizeof(uint32_t));
    }

    ifs.close();

    return true;
}

}
}

#endif // __STL_HPP__
<|endoftext|>


<commit_before>#include "serializer.hpp"
#include <boost/asio.hpp>

namespace Rapscallion {

struct Connection {
  : public boost::enable_shared_from_this<Connection>
{
  constexpr size_t buffersize = 16384;
  Connection(tcp::socket&& socket, std::function<void(const char*, size_t)> onRead)
    : socket(std::move(socket))
    , onRead(onRead)
  {
  }

  tcp::socket& getSocket() {
    return socket_;
  }

  void start() {
    socket_.async_read_some(boost::asio::buffer(data_, max_length),
        boost::bind(&session::handle_read, this,
          boost::asio::placeholders::error,
          boost::asio::placeholders::bytes_transferred));
  }

  void write(const char* buffer, size_t size) {
    // We cannot send packets larger than the buffer size, as we cannot guarantee no interleaving happens.
    if (size > buffersize) throw runtime_error("Packet too large for connection");
    std::lock_guard<std::mutex> l(writeMutex);

    // TODO: wait on cond var for connection to have enough space for this as a single write in the buffer

    memcpy(currentWrite + writeoff, buffer, size);
    writeoff += size;
    if (!writeActive) {
      queueWrite(l);
    }
  }

private:
  void handle_read(const boost::system::error_code& error, size_t bytes_transferred) {
    if (!error) {
      OnRead(buffer, bytes_transferred);
      socket_.async_read_some(boost::asio::buffer(buffer, buffersize),
        [self = std::shared_from_this()](const boost::system::error_code& err, size_t transferred){
          handle_read(err, transferred);
        }
      );
    }
  }

  void queueWrite(const std::lock_guard<std::mutex>&) {
    boost::asio::async_write(socket_, boost::asio::buffer(currentWrite, bytes_transferred),
      [self = std::shared_from_this()](boost::system::error_code& err) {
        handle_write(err);
      }
    );
    currentWrite = (currentWrite == writebuffer1) ? writebuffer2 : writebuffer1;
    writeoff = 0;
    writeActive = true;
    // signal condvar all
  }

  void handle_write(const boost::system::error_code& error) {
    if (!error) {
      std::lock_guard<std::mutex> l(writeMutex);
      if (writeoff > 0) {
        queueWrite(l);
      } else {
        writeActive = false;
      }
    }
  }

private:
  tcp::socket socket;
  char buffer[buffersize];
  char writebuffer1[buffersize];
  char writebuffer2[buffersize];
  size_t writeoff = 0;
  char* currentWrite = writebuffer1;
  std::mutex writeMutex;
};

struct Server {
  boost::asio::io_service& io_service;
  tcp::acceptor acceptor_;
  Server(uint16_t port, std::function<std::shared_ptr<Connection>> onConnect)
    : acceptor_(io_service, tcp::endpoint(tcp::v4(), 13))
    , onConnect(onConnect)
  {
    accept_one();
  }

  void accept_one() {
    std::shared_ptr<Connection> c = std::make_shared<Connection>(acceptor_.get_io_service());
    acceptor_.async_accept(c.getSocket(), [c](boost::system::error_code& ec) {
      if (!ec) {
        onConnect(c);
      }
      accept_one();
    });
  }

  void start_accept()
  {
    std::shared_ptr<Connection> c = std::make_shared<Connection>(acceptor_.get_io_service());
    acceptor_.async_accept(new_connection->socket(), [c = std::move(c)](boost::system::error_code ec){
      if (!error)
      {
        new_connection->start();
      }

      start_accept();
    });
  }
};

#include "connection.h"
#include <thread>
#include <vector>
#include "serializer.h"
#include <cstring>

#include <unistd.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h>

#ifndef MSG_NOSIGNAL
#define MSG_NOSIGNAL 0
#endif

#ifndef MSG_MORE
#define MSG_MORE 0
#endif

namespace rapscallion {

namespace {
  static uint8_t header[8] = { 0x0A, 0xCA, 0x11, 0x10, 0x01, 0x00, 0x00, 0x00 };

  bool writesocket(int fd, const void *buf, size_t bytes) {
    const char *sb = (const char *)buf;
    do {
      int written = send(fd, sb, (int)bytes, MSG_NOSIGNAL | 0);
      if (written < 0) {
        return false;
      } else {
        sb += written;
        bytes -= written;
      }
    } while (bytes);
    return true;
  }
}

Connection::Connection(int fd)
: fd(fd)
{
  pipe(p);
  writesocket(fd, header, sizeof(header));
}

Connection::Connection(const std::string& server, const std::string& port)
{
  pipe(p);
  struct addrinfo hints, *addrinfos;
  memset(&hints, 0, sizeof(hints));
  hints.ai_family = AF_INET;
  hints.ai_socktype = SOCK_STREAM;
  getaddrinfo(server.c_str(), port.c_str(), &hints, &addrinfos);
  fd = socket(addrinfos->ai_family, addrinfos->ai_socktype, addrinfos->ai_protocol);
  int nodelay = 1;
  setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&nodelay, sizeof(nodelay));
  connect(fd, addrinfos->ai_addr, addrinfos->ai_addrlen);
  freeaddrinfo(addrinfos);
  writesocket(fd, header, sizeof(header));
}

void Connection::startReceive(Callback& cb) {
  this->cb = &cb;
  std::shared_ptr<Connection> sharedthis = shared_from_this();
  std::thread readerThread([sharedthis]{ sharedthis->receive(); });
  readerThread.detach();
}

Connection::~Connection()
{
  ::close(fd);
  ::close(p[0]);
  ::close(p[1]);
}

void Connection::Stop() {
  if (stopped)
    return;
  stopped = true;
  write(p[1], "X", 1);
}

void Connection::send(Serializer& s) {
  if (stopped) return;
  std::unique_lock<std::mutex> lock(m);
  const auto& buffer = s.data();
  if (!writesocket(fd, buffer.first, buffer.second))
    Stop();
}

void Connection::receive() {
  uint8_t buffer[1024];
  bool gotHeader = false;
  fd_set fds;
  try {
    while (true) {
      FD_ZERO(&fds);
      FD_SET(fd, &fds);
      FD_SET(p[0], &fds);
      select(std::max(fd, p[0]) + 1, &fds, NULL, NULL, NULL);
      if (FD_ISSET(p[0], &fds))
        return;

      int bytesRead = ::recv(fd, buffer, 1024, 0);
      if (bytesRead <= 0) {
        std::unique_lock<std::mutex> lock(m);
        Stop();
        return;
      }

      receiveBuffer.insert(receiveBuffer.end(), buffer, buffer+bytesRead);
      size_t offset = 0;
      if (!gotHeader) {
        if (receiveBuffer.size() >= 8) {
          if (memcmp(receiveBuffer.data(), header, sizeof(header)) != 0) {
            // Incompatible client, disconnect
            return;
          }
          offset = 8;
        }
      }

      if (gotHeader) {
        while (Deserializer::PacketSize(receiveBuffer, offset) >= (int64_t)(receiveBuffer.size() - offset)) {
          Deserializer s(receiveBuffer, offset);
          offset += Deserializer::PacketSize(receiveBuffer, offset);
          cb->onPacket(s);
        }
      }
    }
  } catch (...) {}
}

}
<commit_msg>Transfer<commit_after>#include "serializer.hpp"
#include <boost/asio.hpp>

namespace Rapscallion {

struct RpcHost {
  template <typename T>
  void Register(T* handler) {
    RegisterStub(new T::Stub(handler));
  }
  template <typename T>
  T* Get(Connection* conn) {
    T* proxy = new T::Proxy(this);
    RegisterProxy(proxy);
    return proxy;
  }
};

struct Connection {
  : public boost::enable_shared_from_this<Connection>
{
  constexpr size_t buffersize = 16384;
  Connection(tcp::socket&& socket, std::function<void(const char*, size_t)> onRead)
    : socket(std::move(socket))
    , onRead(onRead)
  {
  }

  tcp::socket& getSocket() {
    return socket_;
  }

  void start() {
    socket_.async_read_some(boost::asio::buffer(data_, max_length),
        boost::bind(&session::handle_read, this,
          boost::asio::placeholders::error,
          boost::asio::placeholders::bytes_transferred));
  }

  void write(const char* buffer, size_t size) {
    // We cannot send packets larger than the buffer size, as we cannot guarantee no interleaving happens.
    if (size > buffersize) throw runtime_error("Packet too large for connection");
    std::lock_guard<std::mutex> l(writeMutex);

    // TODO: wait on cond var for connection to have enough space for this as a single write in the buffer

    memcpy(currentWrite + writeoff, buffer, size);
    writeoff += size;
    if (!writeActive) {
      queueWrite(l);
    }
  }

private:
  void handle_read(const boost::system::error_code& error, size_t bytes_transferred) {
    if (!error) {
      OnRead(buffer, bytes_transferred);
      socket_.async_read_some(boost::asio::buffer(buffer, buffersize),
        [self = std::shared_from_this()](const boost::system::error_code& err, size_t transferred){
          handle_read(err, transferred);
        }
      );
    }
  }

  void queueWrite(const std::lock_guard<std::mutex>&) {
    boost::asio::async_write(socket_, boost::asio::buffer(currentWrite, bytes_transferred),
      [self = std::shared_from_this()](boost::system::error_code& err) {
        handle_write(err);
      }
    );
    currentWrite = (currentWrite == writebuffer1) ? writebuffer2 : writebuffer1;
    writeoff = 0;
    writeActive = true;
    // signal condvar all
  }

  void handle_write(const boost::system::error_code& error) {
    if (!error) {
      std::lock_guard<std::mutex> l(writeMutex);
      if (writeoff > 0) {
        queueWrite(l);
      } else {
        writeActive = false;
      }
    }
  }

private:
  tcp::socket socket;
  char buffer[buffersize];
  char writebuffer1[buffersize];
  char writebuffer2[buffersize];
  size_t writeoff = 0;
  char* currentWrite = writebuffer1;
  std::mutex writeMutex;
};

struct Server {
  boost::asio::io_service& io_service;
  tcp::acceptor acceptor_;
  Server(uint16_t port, std::function<std::shared_ptr<Connection>> onConnect)
    : acceptor_(io_service, tcp::endpoint(tcp::v4(), 13))
    , onConnect(onConnect)
  {
    accept_one();
  }

  void accept_one() {
    std::shared_ptr<Connection> c = std::make_shared<Connection>(acceptor_.get_io_service());
    acceptor_.async_accept(c.getSocket(), [c](boost::system::error_code& ec) {
      if (!ec) {
        onConnect(c);
      }
      accept_one();
    });
  }

  void start_accept()
  {
    std::shared_ptr<Connection> c = std::make_shared<Connection>(acceptor_.get_io_service());
    acceptor_.async_accept(new_connection->socket(), [c = std::move(c)](boost::system::error_code ec){
      if (!error)
      {
        new_connection->start();
      }

      start_accept();
    });
  }
};

#include "connection.h"
#include <thread>
#include <vector>
#include "serializer.h"
#include <cstring>

#include <unistd.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h>

#ifndef MSG_NOSIGNAL
#define MSG_NOSIGNAL 0
#endif

#ifndef MSG_MORE
#define MSG_MORE 0
#endif

namespace rapscallion {

namespace {
  static uint8_t header[8] = { 0x0A, 0xCA, 0x11, 0x10, 0x01, 0x00, 0x00, 0x00 };

  bool writesocket(int fd, const void *buf, size_t bytes) {
    const char *sb = (const char *)buf;
    do {
      int written = send(fd, sb, (int)bytes, MSG_NOSIGNAL | 0);
      if (written < 0) {
        return false;
      } else {
        sb += written;
        bytes -= written;
      }
    } while (bytes);
    return true;
  }
}

Connection::Connection(int fd)
: fd(fd)
{
  pipe(p);
  writesocket(fd, header, sizeof(header));
}

Connection::Connection(const std::string& server, const std::string& port)
{
  pipe(p);
  struct addrinfo hints, *addrinfos;
  memset(&hints, 0, sizeof(hints));
  hints.ai_family = AF_INET;
  hints.ai_socktype = SOCK_STREAM;
  getaddrinfo(server.c_str(), port.c_str(), &hints, &addrinfos);
  fd = socket(addrinfos->ai_family, addrinfos->ai_socktype, addrinfos->ai_protocol);
  int nodelay = 1;
  setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&nodelay, sizeof(nodelay));
  connect(fd, addrinfos->ai_addr, addrinfos->ai_addrlen);
  freeaddrinfo(addrinfos);
  writesocket(fd, header, sizeof(header));
}

void Connection::startReceive(Callback& cb) {
  this->cb = &cb;
  std::shared_ptr<Connection> sharedthis = shared_from_this();
  std::thread readerThread([sharedthis]{ sharedthis->receive(); });
  readerThread.detach();
}

Connection::~Connection()
{
  ::close(fd);
  ::close(p[0]);
  ::close(p[1]);
}

void Connection::Stop() {
  if (stopped)
    return;
  stopped = true;
  write(p[1], "X", 1);
}

void Connection::send(Serializer& s) {
  if (stopped) return;
  std::unique_lock<std::mutex> lock(m);
  const auto& buffer = s.data();
  if (!writesocket(fd, buffer.first, buffer.second))
    Stop();
}

void Connection::receive() {
  uint8_t buffer[1024];
  bool gotHeader = false;
  fd_set fds;
  try {
    while (true) {
      FD_ZERO(&fds);
      FD_SET(fd, &fds);
      FD_SET(p[0], &fds);
      select(std::max(fd, p[0]) + 1, &fds, NULL, NULL, NULL);
      if (FD_ISSET(p[0], &fds))
        return;

      int bytesRead = ::recv(fd, buffer, 1024, 0);
      if (bytesRead <= 0) {
        std::unique_lock<std::mutex> lock(m);
        Stop();
        return;
      }

      receiveBuffer.insert(receiveBuffer.end(), buffer, buffer+bytesRead);
      size_t offset = 0;
      if (!gotHeader) {
        if (receiveBuffer.size() >= 8) {
          if (memcmp(receiveBuffer.data(), header, sizeof(header)) != 0) {
            // Incompatible client, disconnect
            return;
          }
          offset = 8;
        }
      }

      if (gotHeader) {
        while (Deserializer::PacketSize(receiveBuffer, offset) >= (int64_t)(receiveBuffer.size() - offset)) {
          Deserializer s(receiveBuffer, offset);
          offset += Deserializer::PacketSize(receiveBuffer, offset);
          cb->onPacket(s);
        }
      }
    }
  } catch (...) {}
}

}
<|endoftext|>


<commit_before>#include <cassert>
#include <algorithm>
#include "proc.hh"
#include "io.hh"

namespace ten {

static std::atomic<uint64_t> taskidgen(0);

void tasksleep(uint64_t ms) {
    task::cancellation_point cancellable;
    this_proc()->sched().sleep(milliseconds(ms));
}

bool fdwait(int fd, int rw, optional_timeout ms) {
    task::cancellation_point cancellable;
    return this_proc()->sched().fdwait(fd, rw, ms);
}

int taskpoll(pollfd *fds, nfds_t nfds, optional_timeout ms) {
    task::cancellation_point cancellable;
    return this_proc()->sched().poll(fds, nfds, ms);
}

uint64_t taskspawn(const std::function<void ()> &f, size_t stacksize) {
    task *t = this_proc()->newtaskinproc(f, stacksize);
    t->ready(true); // add new tasks to front of runqueue
    return t->id;
}

uint64_t taskid() {
    DCHECK(this_proc());
    DCHECK(this_task());
    return this_task()->id;
}

int64_t taskyield() {
    task::cancellation_point cancellable;
    proc *p = this_proc();
    uint64_t n = p->nswitch;
    task *t = p->ctask;
    t->ready();
    taskstate("yield");
    t->swap();
    DVLOG(5) << "yield: " << (int64_t)(p->nswitch - n - 1);
    return p->nswitch - n - 1;
}

void tasksystem() {
    proc *p = this_proc();
    p->mark_system_task();
}

bool taskcancel(uint64_t id) {
    proc *p = this_proc();
    DCHECK(p) << "BUG: taskcancel called in null proc";
    return p->cancel_task_by_id(id);
}

const char *taskname(const char *fmt, ...)
{
    task *t = this_task();
    if (fmt && strlen(fmt)) {
        va_list arg;
        va_start(arg, fmt);
        t->vsetname(fmt, arg);
        va_end(arg);
    }
    return t->name;
}

const char *taskstate(const char *fmt, ...)
{
	task *t = this_task();
    if (fmt && strlen(fmt)) {
        va_list arg;
        va_start(arg, fmt);
        t->vsetstate(fmt, arg);
        va_end(arg);
    }
    return t->state;
}

std::string taskdump() {
    std::stringstream ss;
    proc *p = this_proc();
    DCHECK(p) << "BUG: taskdump called in null proc";
    p->dump_tasks(ss);
    return ss.str();
}

void taskdumpf(FILE *of) {
    std::string dump = taskdump();
    fwrite(dump.c_str(), sizeof(char), dump.size(), of);
    fflush(of);
}

task::task(const std::function<void ()> &f, size_t stacksize)
    : co(task::start, this, stacksize)
{
    clear();
    fn = f;
}

void task::init(const std::function<void ()> &f) {
    fn = f;
    co.restart(task::start, this);
}

void task::ready(bool front) {
    proc *p = cproc;
    if (!_ready.exchange(true)) {
        p->ready(this, front);
    }
}

task::~task() {
    clear(false);
}

void task::clear(bool newid) {
    fn = nullptr;
    cancel_points = 0;
    _ready = false;
    systask = false;
    canceled = false;
    if (newid) {
        id = ++taskidgen;
        setname("task[%ju]", id);
        setstate("new");
    }
    exception = nullptr;
    cproc = nullptr;
}

void task::safe_swap() noexcept {
    // swap to scheduler coroutine
    co.swap(&this_proc()->sched_coro());
}

void task::swap() {
    // swap to scheduler coroutine
    co.swap(&this_proc()->sched_coro());

    if (canceled && cancel_points > 0) {
        DVLOG(5) << "THROW INTERRUPT: " << this << "\n" << saved_backtrace().str();
        throw task_interrupted();
    }

    if (exception) {
        DVLOG(5) << "THROW TIMEOUT: " << this << "\n" << saved_backtrace().str();
        std::exception_ptr tmp = nullptr;
        std::swap(tmp, exception);
        std::rethrow_exception(tmp);
    }
}

deadline::deadline(optional_timeout timeout) {
    if (timeout) {
        if (timeout->count() == 0)
            throw errorx("zero optional_deadline - misuse of optional");
        _set_deadline(*timeout);
    }
}

struct deadline_pimpl {
    io_scheduler::alarm_clock::scoped_alarm alarm;
};

deadline::deadline(milliseconds ms) {
    _set_deadline(ms);
}

void deadline::_set_deadline(milliseconds ms) {
    if (ms.count() < 0)
        throw errorx("negative deadline: %jdms", intmax_t(ms.count()));
    if (ms.count() > 0) {
        proc *p = this_proc();
        task *t = this_task();
        auto now = p->cached_time();
        _pimpl.reset(new deadline_pimpl{});
        _pimpl->alarm = std::move(io_scheduler::alarm_clock::scoped_alarm{
                p->sched().alarms, t, ms+now, deadline_reached{}
                });
    }
}

void deadline::cancel() {
    if (_pimpl) {
        _pimpl->alarm.cancel();
    }
}

deadline::~deadline() {
    cancel();
}

milliseconds deadline::remaining() const {
    if (_pimpl) {
        return _pimpl->alarm.remaining();
    }
    return {};
}

task::cancellation_point::cancellation_point() {
    task *t = this_task();
    ++t->cancel_points;
}

task::cancellation_point::~cancellation_point() {
    task *t = this_task();
    --t->cancel_points;
}

} // end namespace ten
<commit_msg>don't throw deadline exception when no cancel_points. minor cleanup<commit_after>#include <cassert>
#include <algorithm>
#include "proc.hh"
#include "io.hh"

namespace ten {

static std::atomic<uint64_t> taskidgen(0);

void tasksleep(uint64_t ms) {
    task::cancellation_point cancellable;
    this_proc()->sched().sleep(milliseconds(ms));
}

bool fdwait(int fd, int rw, optional_timeout ms) {
    task::cancellation_point cancellable;
    return this_proc()->sched().fdwait(fd, rw, ms);
}

int taskpoll(pollfd *fds, nfds_t nfds, optional_timeout ms) {
    task::cancellation_point cancellable;
    return this_proc()->sched().poll(fds, nfds, ms);
}

uint64_t taskspawn(const std::function<void ()> &f, size_t stacksize) {
    task *t = this_proc()->newtaskinproc(f, stacksize);
    t->ready(true); // add new tasks to front of runqueue
    return t->id;
}

uint64_t taskid() {
    DCHECK(this_proc());
    DCHECK(this_task());
    return this_task()->id;
}

int64_t taskyield() {
    task::cancellation_point cancellable;
    proc *p = this_proc();
    uint64_t n = p->nswitch;
    task *t = p->ctask;
    t->ready();
    taskstate("yield");
    t->swap();
    DVLOG(5) << "yield: " << (int64_t)(p->nswitch - n - 1);
    return p->nswitch - n - 1;
}

void tasksystem() {
    proc *p = this_proc();
    p->mark_system_task();
}

bool taskcancel(uint64_t id) {
    proc *p = this_proc();
    DCHECK(p) << "BUG: taskcancel called in null proc";
    return p->cancel_task_by_id(id);
}

const char *taskname(const char *fmt, ...)
{
    task *t = this_task();
    if (fmt && strlen(fmt)) {
        va_list arg;
        va_start(arg, fmt);
        t->vsetname(fmt, arg);
        va_end(arg);
    }
    return t->name;
}

const char *taskstate(const char *fmt, ...)
{
	task *t = this_task();
    if (fmt && strlen(fmt)) {
        va_list arg;
        va_start(arg, fmt);
        t->vsetstate(fmt, arg);
        va_end(arg);
    }
    return t->state;
}

std::string taskdump() {
    std::stringstream ss;
    proc *p = this_proc();
    DCHECK(p) << "BUG: taskdump called in null proc";
    p->dump_tasks(ss);
    return ss.str();
}

void taskdumpf(FILE *of) {
    std::string dump = taskdump();
    fwrite(dump.c_str(), sizeof(char), dump.size(), of);
    fflush(of);
}

task::task(const std::function<void ()> &f, size_t stacksize)
    : co(task::start, this, stacksize)
{
    clear();
    fn = f;
}

void task::init(const std::function<void ()> &f) {
    fn = f;
    co.restart(task::start, this);
}

void task::ready(bool front) {
    proc *p = cproc;
    if (!_ready.exchange(true)) {
        p->ready(this, front);
    }
}

task::~task() {
    clear(false);
}

void task::clear(bool newid) {
    fn = nullptr;
    cancel_points = 0;
    _ready = false;
    systask = false;
    canceled = false;
    if (newid) {
        id = ++taskidgen;
        setname("task[%ju]", id);
        setstate("new");
    }
    exception = nullptr;
    cproc = nullptr;
}

void task::safe_swap() noexcept {
    // swap to scheduler coroutine
    co.swap(&this_proc()->sched_coro());
}

void task::swap() {
    // swap to scheduler coroutine
    co.swap(&this_proc()->sched_coro());

    if (canceled && cancel_points > 0) {
        DVLOG(5) << "THROW INTERRUPT: " << this << "\n" << saved_backtrace().str();
        throw task_interrupted();
    }

    if (exception && cancel_points > 0) {
        DVLOG(5) << "THROW TIMEOUT: " << this << "\n" << saved_backtrace().str();
        std::exception_ptr tmp = nullptr;
        std::swap(tmp, exception);
        std::rethrow_exception(tmp);
    }
}

struct deadline_pimpl {
    io_scheduler::alarm_clock::scoped_alarm alarm;
};

deadline::deadline(optional_timeout timeout) {
    if (timeout) {
        if (timeout->count() == 0)
            throw errorx("zero optional_deadline - misuse of optional");
        _set_deadline(*timeout);
    }
}

deadline::deadline(milliseconds ms) {
    _set_deadline(ms);
}

void deadline::_set_deadline(milliseconds ms) {
    if (ms.count() < 0)
        throw errorx("negative deadline: %jdms", intmax_t(ms.count()));
    if (ms.count() > 0) {
        proc *p = this_proc();
        task *t = this_task();
        auto now = p->cached_time();
        _pimpl.reset(new deadline_pimpl{});
        _pimpl->alarm = std::move(io_scheduler::alarm_clock::scoped_alarm{
                p->sched().alarms, t, ms+now, deadline_reached{}
                });
        DVLOG(5) << "deadline alarm armed: " << _pimpl->alarm._armed << " in " << ms.count() << "ms";
    }
}

void deadline::cancel() {
    if (_pimpl) {
        _pimpl->alarm.cancel();
    }
}

deadline::~deadline() {
    cancel();
}

milliseconds deadline::remaining() const {
    if (_pimpl) {
        return _pimpl->alarm.remaining();
    }
    return {};
}

task::cancellation_point::cancellation_point() {
    task *t = this_task();
    ++t->cancel_points;
}

task::cancellation_point::~cancellation_point() {
    task *t = this_task();
    --t->cancel_points;
}

} // end namespace ten
<|endoftext|>


<commit_before>#include <cstdio>
#include <ctime>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <thread>
#include <mutex>
#include "statistic.h"
#include "solver.h"
using namespace std;

solver yasat;
mutex locker;
int solveDone = 0;
vector<int> result;
Statistic statistic;

void helpMessage() {
    puts("Unexpected parameter");
    puts("./yasat [options] testcase.cnf");
    puts("");
    puts("options: ");
    puts("  -statistic: print statitic result to stderr");
    puts("  -stdout   : print result to stdout instead of file");
    puts("  -no       : init var randomly");
    puts("  -mom      : (default) init var score by MOM");
    puts("  -ruby     : use ruby sequence to restart");
    puts("  -stupid   : restart rapidly stupidly");
    puts("  -novsids  : disable Variable State Independent Decaying Sum heuristic");
    puts("  -nomulti  : disable multi-thread running all method concurrently");
    puts("  -phase    : phase saving");
    puts("  -rand     : add random factor in VSISD");
    puts("  -pos      : pick positive phase while tie");
    puts("  -pre      : enable advance preprocess");
}

// Worker for -xxx
struct WorkerAttr {
    const char *file;
    int mode;
    WorkerAttr(const char *file, int mode)
    :file(file), mode(mode) {}
};
void xxxWorker(WorkerAttr attr) {
    solver worker = yasat;

    worker.solve(attr.mode);

    lock_guard<std::mutex> lock(locker);
    if( !solveDone ) {
        solveDone = 1;
        result = worker.result();
        statistic = worker.statistic;
    }
}

int main(int argc, const char *argv[]) {
    if( argc < 2 ) {
        helpMessage();
        exit(1);
    }

    srand(time(NULL));

    bool stat = false;
    long mode = solver::HEURISTIC_VSIDS | solver::HEURISTIC_MOM_INIT;

    // Parse input parameter
    int srcid = 0, toStdout = 0, xxx = 1;
    for(int i=1, init=false; i<argc; ++i)
        if( argv[i][0] != '-' && !init ) {
            init = true;
            srcid = i;
            yasat.init(argv[srcid]);
        }
        else if( strcmp(argv[i], "-statistic") == 0 ) {
            stat = true;
        }
        else if( strcmp(argv[i], "-stdout") == 0 ) {
            toStdout = 1;
        }
        else if( strcmp(argv[i], "-no") == 0 ) {
            mode &= ~solver::HEURISTIC_MOM_INIT;
            mode |= solver::HEURISTIC_NO_INIT;
            xxx = 0;
        }
        else if( strcmp(argv[i], "-mom") == 0 ) {
            mode &= ~solver::HEURISTIC_NO_INIT;
            mode |= solver::HEURISTIC_MOM_INIT;
            xxx = 0;
        }
        else if( strcmp(argv[i], "-novsids") == 0 ) {
            mode &= ~solver::HEURISTIC_VSIDS;
            xxx = 0;
        }
        else if( strcmp(argv[i], "-nomulti") == 0 ) {
            xxx = 0;
        }
        else if( strcmp(argv[i], "-ruby") == 0 ) {
            mode |= solver::RESTART_RUBY;
            xxx = 0;
        }
        else if( strcmp(argv[i], "-stupid") == 0 ) {
            mode |= solver::RESTART_STUPID;
            xxx = 0;
        }
        else if( strcmp(argv[i], "-pre") == 0 ) {
            mode |= solver::PREPROCESS;
            xxx = 0;
        }
        else if( strcmp(argv[i], "-rand") == 0 ) {
            mode |= solver::RAND;
            xxx = 0;
        }
        else if( strcmp(argv[i], "-pos") == 0 ) {
            mode |= solver::POS;
            xxx = 0;
        }
        else if( strcmp(argv[i], "-phase") == 0 ) {
            mode |= solver::PHASESAVING;
            xxx = 0;
        }
        else {
            helpMessage();
            exit(1);
        }

    if( !srcid ) {
        helpMessage();
        exit(1);
    }

    if( xxx && yasat.size() > 150 ) {

        thread mom(xxxWorker, WorkerAttr(
            argv[srcid],
            solver::HEURISTIC_VSIDS | solver::HEURISTIC_MOM_INIT));
        thread ruby(xxxWorker, WorkerAttr(
            argv[srcid],
            solver::HEURISTIC_VSIDS | solver::HEURISTIC_MOM_INIT | solver::RESTART_RUBY));
        thread rubyPos(xxxWorker, WorkerAttr(
            argv[srcid],
            solver::HEURISTIC_VSIDS | solver::HEURISTIC_MOM_INIT | solver::RESTART_RUBY | solver::POS));
        thread rubyRand(xxxWorker, WorkerAttr(
            argv[srcid],
            solver::HEURISTIC_VSIDS | solver::HEURISTIC_MOM_INIT | solver::RESTART_RUBY | solver::RAND));
        if( mom.joinable() )
            mom.join();
        if( ruby.joinable() )
            ruby.join();
        if( rubyPos.joinable() )
            rubyPos.join();
        if( rubyRand.joinable() )
            rubyRand.join();

    }
    else {
        yasat.solve(mode);
        result = yasat.result();
        statistic = yasat.statistic;
    }

    // Print result
    if( stat ) {
        fprintf(stderr, "================ statistic ================\n");
        fprintf(stderr, "Time on SAT solver: %.3f sec (preprocess %.2f%%)\n", statistic.elapseTime(),
            100.0*statistic.preprocessTime/statistic.elapseTime());
        fprintf(stderr, "Pre learnt assign : %d\n", statistic.preLearntAssignment);
        fprintf(stderr, "Pre learnt clause : %d\n", statistic.preLearntClause);
        fprintf(stderr, "Pre eliminate cls : %d\n", statistic.preEliminateCls);
        fprintf(stderr, "Pre eliminate lit : %d\n", statistic.preEliminateLit);
        fprintf(stderr, "Backtrack num     : %d\n", statistic.backtrackNum);
        fprintf(stderr, "Max depth         : %d\n", statistic.maxDepth);
        fprintf(stderr, "Learnt clause     : %d\n", statistic.learnCls);
        fprintf(stderr, "Avg Learnt Cls Sz : %.2f\n", statistic.learnCls ? double(statistic.totalLearntSz)/statistic.learnCls : 0);
        fprintf(stderr, "Max Learnt Cls Sz : %d\n", statistic.maxLearntSz);
        fprintf(stderr, "Learnt assignment : %d\n", statistic.learnAssignment);
        fprintf(stderr, "Max JumpBack      : %d\n", statistic.maxJumpBack);
        fprintf(stderr, "Restart           : %d\n", statistic.restartTime);
        fprintf(stderr, "===========================================\n");
    }

    if( !toStdout ) {
        fflush(stdout);
        char filename[100];
        strcpy(filename, argv[srcid]);
        int len = strlen(filename);
        if( len>=4  && filename[len-4]=='.' && filename[len-3] == 'c' &&
                filename[len-2] == 'n' && filename[len-1]=='f' ) {
            filename[len-3] = 's';
            filename[len-2] = 'a';
            filename[len-1] = 't';
        }
        else {
            filename[len] = '.';
            filename[len+1] = 's';
            filename[len+2] = 'a';
            filename[len+3] = 't';
            filename[len+4] = '\0';
        }
        freopen(filename, "w", stdout);
    }

    if( result[0] ) {
        puts("s SATISFIABLE");
        putchar('v');
        for(int i=1; i<result.size(); ++i)
            printf(" %d", result[i]);
        puts(" 0");
    }
    else {
        puts("s UNSATISFIABLE");
    }
    return 0;
}
<commit_msg>Update multi thread version<commit_after>#include <cstdio>
#include <ctime>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <thread>
#include <mutex>
#include "statistic.h"
#include "solver.h"
using namespace std;

solver yasat;
mutex locker;
int solveDone = 0;
vector<int> result;
Statistic statistic;

void helpMessage() {
    puts("Unexpected parameter");
    puts("./yasat [options] testcase.cnf");
    puts("");
    puts("options: ");
    puts("  -statistic: print statitic result to stderr");
    puts("  -stdout   : print result to stdout instead of file");
    puts("  -no       : init var randomly");
    puts("  -mom      : (default) init var score by MOM");
    puts("  -ruby     : use ruby sequence to restart");
    puts("  -stupid   : restart rapidly stupidly");
    puts("  -novsids  : disable Variable State Independent Decaying Sum heuristic");
    puts("  -nomulti  : disable multi-thread running all method concurrently");
    puts("  -phase    : phase saving");
    puts("  -rand     : add random factor in VSISD");
    puts("  -pos      : pick positive phase while tie");
    puts("  -pre      : enable advance preprocess");
}

// Worker for -xxx
struct WorkerAttr {
    const char *file;
    int mode;
    WorkerAttr(const char *file, int mode)
    :file(file), mode(mode) {}
};
void xxxWorker(WorkerAttr attr) {
    solver worker = yasat;

    worker.solve(attr.mode);

    lock_guard<std::mutex> lock(locker);
    if( !solveDone ) {
        solveDone = 1;
        result = worker.result();
        statistic = worker.statistic;
    }
}

int main(int argc, const char *argv[]) {
    if( argc < 2 ) {
        helpMessage();
        exit(1);
    }

    srand(time(NULL));

    bool stat = false;
    long mode = solver::HEURISTIC_VSIDS | solver::HEURISTIC_MOM_INIT;

    // Parse input parameter
    int srcid = 0, toStdout = 0, xxx = 1;
    for(int i=1, init=false; i<argc; ++i)
        if( argv[i][0] != '-' && !init ) {
            init = true;
            srcid = i;
            yasat.init(argv[srcid]);
        }
        else if( strcmp(argv[i], "-statistic") == 0 ) {
            stat = true;
        }
        else if( strcmp(argv[i], "-stdout") == 0 ) {
            toStdout = 1;
        }
        else if( strcmp(argv[i], "-no") == 0 ) {
            mode &= ~solver::HEURISTIC_MOM_INIT;
            mode |= solver::HEURISTIC_NO_INIT;
            xxx = 0;
        }
        else if( strcmp(argv[i], "-mom") == 0 ) {
            mode &= ~solver::HEURISTIC_NO_INIT;
            mode |= solver::HEURISTIC_MOM_INIT;
            xxx = 0;
        }
        else if( strcmp(argv[i], "-novsids") == 0 ) {
            mode &= ~solver::HEURISTIC_VSIDS;
            xxx = 0;
        }
        else if( strcmp(argv[i], "-nomulti") == 0 ) {
            xxx = 0;
        }
        else if( strcmp(argv[i], "-ruby") == 0 ) {
            mode |= solver::RESTART_RUBY;
            xxx = 0;
        }
        else if( strcmp(argv[i], "-stupid") == 0 ) {
            mode |= solver::RESTART_STUPID;
            xxx = 0;
        }
        else if( strcmp(argv[i], "-pre") == 0 ) {
            mode |= solver::PREPROCESS;
            xxx = 0;
        }
        else if( strcmp(argv[i], "-rand") == 0 ) {
            mode |= solver::RAND;
            xxx = 0;
        }
        else if( strcmp(argv[i], "-pos") == 0 ) {
            mode |= solver::POS;
            xxx = 0;
        }
        else if( strcmp(argv[i], "-phase") == 0 ) {
            mode |= solver::PHASESAVING;
            xxx = 0;
        }
        else {
            helpMessage();
            exit(1);
        }

    if( !srcid ) {
        helpMessage();
        exit(1);
    }

    if( xxx && yasat.size() > 150 ) {

        thread mom(xxxWorker, WorkerAttr(
            argv[srcid],
            solver::HEURISTIC_VSIDS | solver::HEURISTIC_MOM_INIT));
        thread ruby(xxxWorker, WorkerAttr(
            argv[srcid],
            solver::HEURISTIC_VSIDS | solver::HEURISTIC_MOM_INIT | solver::RESTART_RUBY));
        thread rubyPos(xxxWorker, WorkerAttr(
            argv[srcid],
            solver::HEURISTIC_VSIDS | solver::HEURISTIC_MOM_INIT | solver::RESTART_RUBY | solver::POS));
        thread rubyRand(xxxWorker, WorkerAttr(
            argv[srcid],
            solver::HEURISTIC_VSIDS | solver::HEURISTIC_MOM_INIT | solver::RESTART_RUBY | solver::PHASESAVING));
        if( mom.joinable() )
            mom.join();
        if( ruby.joinable() )
            ruby.join();
        if( rubyPos.joinable() )
            rubyPos.join();
        if( rubyRand.joinable() )
            rubyRand.join();

    }
    else {
        yasat.solve(mode);
        result = yasat.result();
        statistic = yasat.statistic;
    }

    // Print result
    if( stat ) {
        fprintf(stderr, "================ statistic ================\n");
        fprintf(stderr, "Time on SAT solver: %.3f sec (preprocess %.2f%%)\n", statistic.elapseTime(),
            100.0*statistic.preprocessTime/statistic.elapseTime());
        fprintf(stderr, "Pre learnt assign : %d\n", statistic.preLearntAssignment);
        fprintf(stderr, "Pre learnt clause : %d\n", statistic.preLearntClause);
        fprintf(stderr, "Pre eliminate cls : %d\n", statistic.preEliminateCls);
        fprintf(stderr, "Pre eliminate lit : %d\n", statistic.preEliminateLit);
        fprintf(stderr, "Backtrack num     : %d\n", statistic.backtrackNum);
        fprintf(stderr, "Max depth         : %d\n", statistic.maxDepth);
        fprintf(stderr, "Learnt clause     : %d\n", statistic.learnCls);
        fprintf(stderr, "Avg Learnt Cls Sz : %.2f\n", statistic.learnCls ? double(statistic.totalLearntSz)/statistic.learnCls : 0);
        fprintf(stderr, "Max Learnt Cls Sz : %d\n", statistic.maxLearntSz);
        fprintf(stderr, "Learnt assignment : %d\n", statistic.learnAssignment);
        fprintf(stderr, "Max JumpBack      : %d\n", statistic.maxJumpBack);
        fprintf(stderr, "Restart           : %d\n", statistic.restartTime);
        fprintf(stderr, "===========================================\n");
    }

    if( !toStdout ) {
        fflush(stdout);
        char filename[100];
        strcpy(filename, argv[srcid]);
        int len = strlen(filename);
        if( len>=4  && filename[len-4]=='.' && filename[len-3] == 'c' &&
                filename[len-2] == 'n' && filename[len-1]=='f' ) {
            filename[len-3] = 's';
            filename[len-2] = 'a';
            filename[len-1] = 't';
        }
        else {
            filename[len] = '.';
            filename[len+1] = 's';
            filename[len+2] = 'a';
            filename[len+3] = 't';
            filename[len+4] = '\0';
        }
        freopen(filename, "w", stdout);
    }

    if( result[0] ) {
        puts("s SATISFIABLE");
        putchar('v');
        for(int i=1; i<result.size(); ++i)
            printf(" %d", result[i]);
        puts(" 0");
    }
    else {
        puts("s UNSATISFIABLE");
    }
    return 0;
}
<|endoftext|>


<commit_before>#include<iostream>
#include<vector>
#include<cstdio>
#include<string>
#include<thread>
#include<dirent.h>
#include<chrono>
#include<sys/socket.h>
#include<netinet/in.h>
#include<sys/types.h>
#include<arpa/inet.h>
#include<fcntl.h>
#include<unistd.h>
#include<cstdlib>
#include<sys/wait.h>
#include<string.h>
#include<mutex>
#define SUCCESS 0
#define FAILURE 1
#define BCAST_PORT 5000
#define REQ_LISTNER_PORT 6000
#define MAX_SIZE 1024
#define CLI_ID "101"
#define TOKEN "#"

std::mutex listner_mutex;

void file_bcast()
{
	int bcast_sockfd;
	int bcast_enable = 1;

	struct sockaddr_in new_addr;

	bcast_sockfd = socket(AF_INET, SOCK_DGRAM, 0);

	memset(&new_addr, 0, sizeof(new_addr));
	setsockopt(bcast_sockfd, SOL_SOCKET, SO_BROADCAST, (void *)&bcast_enable, sizeof(bcast_enable));
	new_addr.sin_family = AF_INET;
	new_addr.sin_port = BCAST_PORT;
	new_addr.sin_addr.s_addr = htonl(INADDR_BROADCAST);

	int bind_status = bind(bcast_sockfd, (struct sockaddr*)&new_addr, sizeof(new_addr));

	while(1)
	{
		std::this_thread::sleep_for(std::chrono::milliseconds(5000));
		DIR *dir;
		struct dirent *ent;

		char fs_data[MAX_SIZE];
		memset(fs_data, 0, MAX_SIZE);
		strcpy(fs_data, CLI_ID);

		if ((dir = opendir ("./")) != NULL)
		{
  			while((ent = readdir (dir)) != NULL)
 			{
				if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
          			{continue;}
				else
				{
					strcat(fs_data, TOKEN);
  					strcat(fs_data, ent->d_name);
          			}
			}
		}
  		closedir (dir);
		std::cout << fs_data << std::endl;
		sendto(bcast_sockfd, fs_data, strlen(fs_data), 0, (struct sockaddr *)&new_addr, sizeof(struct sockaddr_in));

	}
}

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

	std::thread broadcaster(file_bcast);
//	std::thread listener(bcast_listener);
	broadcaster.detach();

//	listener.detach();
	while(1){}

	return SUCCESS;
}

<commit_msg>Logic Problem<commit_after>#include<iostream>
#include<vector>
#include<cstdio>
#include<string>
#include<thread>
#include<dirent.h>
#include<chrono>
#include<sys/socket.h>
#include<netinet/in.h>
#include<sys/types.h>
#include<arpa/inet.h>
#include<fcntl.h>
#include<unistd.h>
#include<cstdlib>
#include<sys/wait.h>
#include<string.h>
#include<mutex>
#define SUCCESS 0
#define FAILURE 1
#define BCAST_PORT 5000
#define REQ_LISTNER_PORT 6000
#define MAX_SIZE 1024
#define CLI_ID "101"
#define TOKEN "#"
#define PORT 54545
std::mutex listner_mutex;

void file_bcast()
{
	//Current Client Socket
	int bcast_sockfd;

	bcast_sockfd = socket(AF_INET, SOCK_DGRAM, 0);

	struct sockaddr_in new_addr;
	memset(&new_addr, 0, sizeof(new_addr));
	new_addr.sin_family = AF_INET;
	new_addr.sin_port = PORT;
	new_addr.sin_addr.s_addr = htonl(INADDR_ANY);

	while(1)
	{
		std::this_thread::sleep_for(std::chrono::milliseconds(5000));
		DIR *dir;
		struct dirent *ent;
		char fs_data[MAX_SIZE];
		memset(fs_data, 0, MAX_SIZE);
		strcpy(fs_data, CLI_ID);

		if ((dir = opendir ("./")) != NULL)
		{
  			while((ent = readdir (dir)) != NULL)
 			{
				if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
          			{continue;}
				else
				{
					strcat(fs_data, TOKEN);
  					strcat(fs_data, ent->d_name);
          			}
			}
		}
  		closedir (dir);
		std::cout << fs_data << std::endl;
		sendto(bcast_sockfd, fs_data, strlen(fs_data), 0, (struct sockaddr *)&new_addr, sizeof(struct sockaddr_in));

	}
}

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

	std::thread broadcaster(file_bcast);
//	std::thread listener(bcast_listener);
	broadcaster.detach();

//	listener.detach();
	while(1){}

	return SUCCESS;
}

<|endoftext|>