<commit_before>
#pragma once

#include "numerics/frequency_analysis.hpp"

#include <algorithm>
#include <functional>
#include <vector>

#include "base/status.hpp"
#include "base/tags.hpp"
#include "geometry/grassmann.hpp"
#include "geometry/hilbert.hpp"
#include "numerics/poisson_series_basis.hpp"
#include "numerics/root_finders.hpp"
#include "numerics/unbounded_arrays.hpp"
#include "quantities/elementary_functions.hpp"

namespace principia {
namespace numerics {
namespace frequency_analysis {
namespace internal_frequency_analysis {

using base::Error;
using base::Status;
using base::uninitialized;
using geometry::Hilbert;
using geometry::Vector;
using quantities::Inverse;
using quantities::IsFinite;
using quantities::Sqrt;
using quantities::Square;
using quantities::SquareRoot;

// Appends basis elements for |ω| to |basis| and |basis_subspaces|.  Returns the
// number of elements that were appended.
template<int aperiodic_degree, int periodic_degree,
         typename BasisSeries>
int MakeBasis(std::optional<AngularFrequency> const& ω,
              Instant const& t_min,
              Instant const& t_max,
              std::vector<BasisSeries>& basis,
              std::vector<PoissonSeriesSubspace>& basis_subspaces) {
  if (ω.value() == AngularFrequency{}) {
    using Generator =
        PoissonSeriesBasisGenerator<BasisSeries, aperiodic_degree>;
    auto const ω_basis = Generator::Basis(t_min, t_max);
    auto const ω_basis_subspaces = Generator::Subspaces();
    std::move(ω_basis.begin(), ω_basis.end(), std::back_inserter(basis));
    std::move(ω_basis_subspaces.begin(),
              ω_basis_subspaces.end(),
              std::back_inserter(basis_subspaces));
    return std::tuple_size_v<decltype(ω_basis)>;
  } else {
    using Generator = PoissonSeriesBasisGenerator<BasisSeries, periodic_degree>;
    auto const ω_basis = Generator::Basis(ω.value(), t_min, t_max);
    auto const ω_basis_subspaces = Generator::Subspaces(ω.value());
    std::move(ω_basis.begin(), ω_basis.end(), std::back_inserter(basis));
    std::move(ω_basis_subspaces.begin(),
              ω_basis_subspaces.end(),
              std::back_inserter(basis_subspaces));
    return std::tuple_size_v<decltype(ω_basis)>;
  }
}

//TODO(phl):comment
template<typename Function, typename BasisSeries,
         int aperiodic_wdegree, int periodic_wdegree,
         template<typename, typename, int> class Evaluator>
Status GramSchmidtStep(
    Function const& aₘ,
    PoissonSeries<double,
                  aperiodic_wdegree, periodic_wdegree, Evaluator> const& weight,
    Instant const& t_min,
    Instant const& t_max,
    std::vector<PoissonSeriesSubspace> const& basis_subspaces,
    std::vector<BasisSeries> const& q,
    BasisSeries& qₘ,
    std::vector<double>& rₘ) {
  // This code follows Björk, Numerics of Gram-Schmidt Orthogonalization,
  // Algorithm 6.1.  It processes one column of q and r at a time.

  static constexpr double α = 0.5;
  int const m = q.size();
  rₘ.resize(m + 1, 0.0);

  Function q̂ₘ = aₘ;

  // Formal integration works for a single basis element.
  double q̂ₘ_norm =
      Sqrt((PointwiseInnerProduct(q̂ₘ, q̂ₘ) * weight).Integrate(t_min, t_max) /
           (t_max - t_min));

  // Loop on p.
  Function previous_q̂ₘ = q̂ₘ;
  double previous_q̂ₘ_norm;
  do {
    previous_q̂ₘ = q̂ₘ;
    previous_q̂ₘ_norm = q̂ₘ_norm;
    for (int i = 0; i < m; ++i) {
      if (!PoissonSeriesSubspace::orthogonal(basis_subspaces[i],
                                             basis_subspaces[m])) {
        double const sᵖₘ =
            InnerProduct(q[i], previous_q̂ₘ, weight, t_min, t_max);
        q̂ₘ -= sᵖₘ * q[i];
        rₘ[i] += sᵖₘ;
      }
    }
    q̂ₘ_norm = q̂ₘ.Norm(weight, t_min, t_max);

    if (!IsFinite(q̂ₘ_norm)) {
      return Status(Error::OUT_OF_RANGE, u8"Unable to compute q̂ₘ_norm");
    }
  } while (q̂ₘ_norm < α * previous_q̂ₘ_norm);

  // Fill the result.
  qₘ = q̂ₘ / q̂ₘ_norm;
  rₘ[m] = q̂ₘ_norm;

  return Status::OK;
}

template<typename Function,
         int aperiodic_wdegree, int periodic_wdegree,
         template<typename, typename, int> class Evaluator>
AngularFrequency PreciseMode(
    Interval<AngularFrequency> const& fft_mode,
    Function const& function,
    PoissonSeries<double,
                  aperiodic_wdegree, periodic_wdegree,
                  Evaluator> const& weight) {
  auto const weighted_function = weight * function;
  auto const weighted_function_spectrum = weighted_function.FourierTransform();

  auto power =
      [&weighted_function_spectrum](AngularFrequency const& ω) {
        return weighted_function_spectrum(ω).Norm²();
      };

  return Brent(power,
               fft_mode.min,
               fft_mode.max,
               std::greater<>());
}

template<int aperiodic_degree, int periodic_degree,
         typename Function,
         int aperiodic_wdegree, int periodic_wdegree,
         template<typename, typename, int> class Evaluator>
PoissonSeries<std::invoke_result_t<Function, Instant>,
              aperiodic_degree, periodic_degree,
              Evaluator>
Projection(Function const& function,
           AngularFrequency const& ω,
           PoissonSeries<double,
                         aperiodic_wdegree, periodic_wdegree,
                         Evaluator> const& weight,
           Instant const& t_min,
           Instant const& t_max) {
  std::optional<AngularFrequency> optional_ω = ω;

  // A calculator that returns optional_ω once and then stops.
  auto angular_frequency_calculator = [&optional_ω](auto const& residual) {
    auto const result = optional_ω;
    optional_ω = std::nullopt;
    return result;
  };

  return IncrementalProjection<aperiodic_degree, periodic_degree>(
      function,
      angular_frequency_calculator,
      weight,
      t_min, t_max);
}

template<int aperiodic_degree, int periodic_degree,
         typename Function,
         typename AngularFrequencyCalculator,
         int aperiodic_wdegree, int periodic_wdegree,
         template<typename, typename, int> class Evaluator>
PoissonSeries<std::invoke_result_t<Function, Instant>,
              aperiodic_degree, periodic_degree,
              Evaluator>
IncrementalProjection(Function const& function,
                      AngularFrequencyCalculator const& calculator,
                      PoissonSeries<double,
                                    aperiodic_wdegree, periodic_wdegree,
                                    Evaluator> const& weight,
                      Instant const& t_min,
                      Instant const& t_max) {
  using Value = std::invoke_result_t<Function, Instant>;
  using Norm = typename Hilbert<Value>::NormType;
  using Normalized = typename Hilbert<Value>::NormalizedType;
  using BasisSeries = PoissonSeries<Normalized,
                                    aperiodic_degree, periodic_degree,
                                    Evaluator>;
  using ResultSeries = PoissonSeries<Value,
                                     aperiodic_degree, periodic_degree,
                                     Evaluator>;

  Instant const& t0 = weight.origin();
  auto const basis_zero = static_cast<
      typename BasisSeries::AperiodicPolynomial>(
      typename PoissonSeries<Normalized, 0, 0, Evaluator>::AperiodicPolynomial(
          {Normalized{}}, t0));
  auto const result_zero =
      static_cast<typename ResultSeries::AperiodicPolynomial>(
          typename PoissonSeries<Value, 0, 0, Evaluator>::AperiodicPolynomial(
              {Value{}}, t0));

  std::optional<AngularFrequency> ω = calculator(function);
  CHECK(ω.has_value());

  std::vector<BasisSeries> basis;
  // The Poisson series basis[k] belongs to the subspace basis_subspaces[k];
  // this remains true after orthonormalization, i.e., q[k] belongs to the
  // subspace basis_subspaces[k] below.
  std::vector<PoissonSeriesSubspace> basis_subspaces;

  int basis_size = MakeBasis<aperiodic_degree, periodic_degree>(
      ω, t_min, t_max, basis, basis_subspaces);

  // This is logically Q in the QR decomposition of basis.
  std::vector<BasisSeries> q;

  // This is logically R in the QR decomposition of basis.
  UnboundedUpperTriangularMatrix<double> r(basis_size);  // Zero-initialized.

  ResultSeries F(result_zero, {{}});
  auto f = function - F;

  int m_begin = 0;
  for (;;) {
    for (int m = m_begin; m < basis_size; ++m) {
      BasisSeries qₘ(basis_zero, {{}});
      std::vector<double> rₘ;

      auto const status = GramSchmidtStep(
          /*aₘ=*/basis[m], weight, t_min, t_max, basis_subspaces, q, qₘ, rₘ);
      if (!status.ok()) {
        return F;
      }

      q.push_back(qₘ);
      DCHECK_EQ(m + 1, q.size());

      Norm const Aₘ = InnerProduct(f, q[m], weight, t_min, t_max);

      auto const Aₘqₘ = Aₘ * q[m];
      f -= Aₘqₘ;
      F += Aₘqₘ;
    }

    ω = calculator(f);
    if (!ω.has_value()) {
      return F;
    }

    int const ω_basis_size = MakeBasis<aperiodic_degree, periodic_degree>(
        ω, t_min, t_max, basis, basis_subspaces);
    m_begin = basis_size;
    basis_size += ω_basis_size;
    r.Extend(basis_size);
  }
}

}  // namespace internal_frequency_analysis
}  // namespace frequency_analysis
}  // namespace numerics
}  // namespace principia
<commit_msg>Fill the QR decomposition.<commit_after>
#pragma once

#include "numerics/frequency_analysis.hpp"

#include <algorithm>
#include <functional>
#include <vector>

#include "base/status.hpp"
#include "base/tags.hpp"
#include "geometry/grassmann.hpp"
#include "geometry/hilbert.hpp"
#include "numerics/poisson_series_basis.hpp"
#include "numerics/root_finders.hpp"
#include "numerics/unbounded_arrays.hpp"
#include "quantities/elementary_functions.hpp"

namespace principia {
namespace numerics {
namespace frequency_analysis {
namespace internal_frequency_analysis {

using base::Error;
using base::Status;
using base::uninitialized;
using geometry::Hilbert;
using geometry::Vector;
using quantities::Inverse;
using quantities::IsFinite;
using quantities::Sqrt;
using quantities::Square;
using quantities::SquareRoot;

// Appends basis elements for |ω| to |basis| and |basis_subspaces|.  Returns the
// number of elements that were appended.
template<int aperiodic_degree, int periodic_degree,
         typename BasisSeries>
int MakeBasis(std::optional<AngularFrequency> const& ω,
              Instant const& t_min,
              Instant const& t_max,
              std::vector<BasisSeries>& basis,
              std::vector<PoissonSeriesSubspace>& basis_subspaces) {
  if (ω.value() == AngularFrequency{}) {
    using Generator =
        PoissonSeriesBasisGenerator<BasisSeries, aperiodic_degree>;
    auto const ω_basis = Generator::Basis(t_min, t_max);
    auto const ω_basis_subspaces = Generator::Subspaces();
    std::move(ω_basis.begin(), ω_basis.end(), std::back_inserter(basis));
    std::move(ω_basis_subspaces.begin(),
              ω_basis_subspaces.end(),
              std::back_inserter(basis_subspaces));
    return std::tuple_size_v<decltype(ω_basis)>;
  } else {
    using Generator = PoissonSeriesBasisGenerator<BasisSeries, periodic_degree>;
    auto const ω_basis = Generator::Basis(ω.value(), t_min, t_max);
    auto const ω_basis_subspaces = Generator::Subspaces(ω.value());
    std::move(ω_basis.begin(), ω_basis.end(), std::back_inserter(basis));
    std::move(ω_basis_subspaces.begin(),
              ω_basis_subspaces.end(),
              std::back_inserter(basis_subspaces));
    return std::tuple_size_v<decltype(ω_basis)>;
  }
}

//TODO(phl):comment
template<typename Function, typename BasisSeries,
         int aperiodic_wdegree, int periodic_wdegree,
         template<typename, typename, int> class Evaluator>
Status GramSchmidtStep(
    Function const& aₘ,
    PoissonSeries<double,
                  aperiodic_wdegree, periodic_wdegree, Evaluator> const& weight,
    Instant const& t_min,
    Instant const& t_max,
    std::vector<PoissonSeriesSubspace> const& basis_subspaces,
    std::vector<BasisSeries> const& q,
    BasisSeries& qₘ,
    std::vector<double>& rₘ) {
  // This code follows Björk, Numerics of Gram-Schmidt Orthogonalization,
  // Algorithm 6.1.  It processes one column of q and r at a time.

  static constexpr double α = 0.5;
  int const m = q.size();
  rₘ.resize(m + 1, 0.0);

  Function q̂ₘ = aₘ;

  // Formal integration works for a single basis element.
  double q̂ₘ_norm =
      Sqrt((PointwiseInnerProduct(q̂ₘ, q̂ₘ) * weight).Integrate(t_min, t_max) /
           (t_max - t_min));

  // Loop on p.
  Function previous_q̂ₘ = q̂ₘ;
  double previous_q̂ₘ_norm;
  do {
    previous_q̂ₘ = q̂ₘ;
    previous_q̂ₘ_norm = q̂ₘ_norm;
    for (int i = 0; i < m; ++i) {
      if (!PoissonSeriesSubspace::orthogonal(basis_subspaces[i],
                                             basis_subspaces[m])) {
        double const sᵖₘ =
            InnerProduct(q[i], previous_q̂ₘ, weight, t_min, t_max);
        q̂ₘ -= sᵖₘ * q[i];
        rₘ[i] += sᵖₘ;
      }
    }
    q̂ₘ_norm = q̂ₘ.Norm(weight, t_min, t_max);

    if (!IsFinite(q̂ₘ_norm)) {
      return Status(Error::OUT_OF_RANGE, u8"Unable to compute q̂ₘ_norm");
    }
  } while (q̂ₘ_norm < α * previous_q̂ₘ_norm);

  // Fill the result.
  qₘ = q̂ₘ / q̂ₘ_norm;
  rₘ[m] = q̂ₘ_norm;

  return Status::OK;
}

template<typename Function,
         int aperiodic_wdegree, int periodic_wdegree,
         template<typename, typename, int> class Evaluator>
AngularFrequency PreciseMode(
    Interval<AngularFrequency> const& fft_mode,
    Function const& function,
    PoissonSeries<double,
                  aperiodic_wdegree, periodic_wdegree,
                  Evaluator> const& weight) {
  auto const weighted_function = weight * function;
  auto const weighted_function_spectrum = weighted_function.FourierTransform();

  auto power =
      [&weighted_function_spectrum](AngularFrequency const& ω) {
        return weighted_function_spectrum(ω).Norm²();
      };

  return Brent(power,
               fft_mode.min,
               fft_mode.max,
               std::greater<>());
}

template<int aperiodic_degree, int periodic_degree,
         typename Function,
         int aperiodic_wdegree, int periodic_wdegree,
         template<typename, typename, int> class Evaluator>
PoissonSeries<std::invoke_result_t<Function, Instant>,
              aperiodic_degree, periodic_degree,
              Evaluator>
Projection(Function const& function,
           AngularFrequency const& ω,
           PoissonSeries<double,
                         aperiodic_wdegree, periodic_wdegree,
                         Evaluator> const& weight,
           Instant const& t_min,
           Instant const& t_max) {
  std::optional<AngularFrequency> optional_ω = ω;

  // A calculator that returns optional_ω once and then stops.
  auto angular_frequency_calculator = [&optional_ω](auto const& residual) {
    auto const result = optional_ω;
    optional_ω = std::nullopt;
    return result;
  };

  return IncrementalProjection<aperiodic_degree, periodic_degree>(
      function,
      angular_frequency_calculator,
      weight,
      t_min, t_max);
}

template<int aperiodic_degree, int periodic_degree,
         typename Function,
         typename AngularFrequencyCalculator,
         int aperiodic_wdegree, int periodic_wdegree,
         template<typename, typename, int> class Evaluator>
PoissonSeries<std::invoke_result_t<Function, Instant>,
              aperiodic_degree, periodic_degree,
              Evaluator>
IncrementalProjection(Function const& function,
                      AngularFrequencyCalculator const& calculator,
                      PoissonSeries<double,
                                    aperiodic_wdegree, periodic_wdegree,
                                    Evaluator> const& weight,
                      Instant const& t_min,
                      Instant const& t_max) {
  using Value = std::invoke_result_t<Function, Instant>;
  using Norm = typename Hilbert<Value>::NormType;
  using Normalized = typename Hilbert<Value>::NormalizedType;
  using BasisSeries = PoissonSeries<Normalized,
                                    aperiodic_degree, periodic_degree,
                                    Evaluator>;
  using ResultSeries = PoissonSeries<Value,
                                     aperiodic_degree, periodic_degree,
                                     Evaluator>;

  Instant const& t0 = weight.origin();
  auto const basis_zero = static_cast<
      typename BasisSeries::AperiodicPolynomial>(
      typename PoissonSeries<Normalized, 0, 0, Evaluator>::AperiodicPolynomial(
          {Normalized{}}, t0));
  auto const result_zero =
      static_cast<typename ResultSeries::AperiodicPolynomial>(
          typename PoissonSeries<Value, 0, 0, Evaluator>::AperiodicPolynomial(
              {Value{}}, t0));

  std::optional<AngularFrequency> ω = calculator(function);
  CHECK(ω.has_value());

  std::vector<BasisSeries> basis;
  // The Poisson series basis[k] belongs to the subspace basis_subspaces[k];
  // this remains true after orthonormalization, i.e., q[k] belongs to the
  // subspace basis_subspaces[k] below.
  std::vector<PoissonSeriesSubspace> basis_subspaces;

  int basis_size = MakeBasis<aperiodic_degree, periodic_degree>(
      ω, t_min, t_max, basis, basis_subspaces);

  // This is logically Q in the QR decomposition of basis.
  std::vector<BasisSeries> q;

  // This is logically R in the QR decomposition of basis.
  UnboundedUpperTriangularMatrix<double> r(basis_size, uninitialized);

  ResultSeries F(result_zero, {{}});
  auto f = function - F;

  int m_begin = 0;
  for (;;) {
    for (int m = m_begin; m < basis_size; ++m) {
      BasisSeries qₘ(basis_zero, {{}});
      std::vector<double> rₘ;

      auto const status = GramSchmidtStep(
          /*aₘ=*/basis[m], weight, t_min, t_max, basis_subspaces, q, qₘ, rₘ);
      if (!status.ok()) {
        return F;
      }

      for (int i = 0; i <=m; ++i) {
        r[i][m] = rₘ[i];
      }
      q.push_back(qₘ);
      DCHECK_EQ(m + 1, q.size());

      Norm const Aₘ = InnerProduct(f, q[m], weight, t_min, t_max);

      auto const Aₘqₘ = Aₘ * q[m];
      f -= Aₘqₘ;
      F += Aₘqₘ;
    }

    ω = calculator(f);
    if (!ω.has_value()) {
      return F;
    }

    int const ω_basis_size = MakeBasis<aperiodic_degree, periodic_degree>(
        ω, t_min, t_max, basis, basis_subspaces);
    m_begin = basis_size;
    basis_size += ω_basis_size;
    r.Extend(basis_size, uninitialized);
  }
}

}  // namespace internal_frequency_analysis
}  // namespace frequency_analysis
}  // namespace numerics
}  // namespace principia
<|endoftext|>


<commit_before>#ifndef PARAMETERHANDLER_HH_INCLUDED
#define PARAMETERHANDLER_HH_INCLUDED

#include <fstream>
#include <ostream>
#include <map>

/**
 *  \brief class processing parameter file
 *
 *  \c ParameterHandler reads a parameter file once and stores all found values internally
 **/
class ParameterHandler
{
    private:
        typedef std::map< std::string, std::string > MapType;
        MapType parameter_map_;
        bool status_;

    public:
        /** \ Please doc me!
         *
         **/
        ParameterHandler( const std::string filename )
            :status_( false )
        {
            ParseParamFile( filename );
        }

        ParameterHandler(  )
            :status_( false )
        {
        }

        /** \brief function used for parametrized ctor and two-step creation
        **/
        bool ParseParamFile( const std::string filename )
        {
            std::ifstream parameter_file( filename.c_str() );
            if( parameter_file.is_open() )
            {
                while( !parameter_file.eof() )
                {
                    std :: string line;
                    std :: getline( parameter_file, line );

                    if( line.size() == 0 )
                        continue;

                    if( (line[ 0 ] != '%') && (line[ 0 ] != '#') )
                    {
                        std::string param_name = line.substr( 0, line.find_first_of(":") );
                        std::string value = line.substr( line.find_first_of(":")+1, line.length() );
                        parameter_map_[param_name] = value;
                    }

                }
                status_ = true;
                parameter_file.close();
            }
            else {
                //LOGERROR
                status_ = false;
                std::cerr << "ERROR: file " << filename << " not found!\n";
            }
            return Ok();
        }

        /**
         *  \brief checks, if a parameter is found in the parameterfile
         *  \arg const std::string name name of the parameter to be found
         *  \return returns true, if the parameter is found
         **/
         bool ParameterExists( const std::string name ) const
         {
             if ( !( status_ ) ) {
                 return false;
             }
             else {
                 MapType::const_iterator it = parameter_map_.find( name );
                 if ( it != parameter_map_.end() ) {
                     return true;
                 }
                 else {
                     return false;
                 }

             }
         }

        /** \todo Please doc me! */
        template < class ReturnType >
        ReturnType GetParameter( const std::string name) const
        {
            if ( !( status_ ) ) {
                return (ReturnType) 0;
            }
            else {
                MapType::const_iterator it = parameter_map_.find( name ) ;
                if ( it != parameter_map_.end() ){
                    return Stuff::fromString<ReturnType>( it->second );
                }
                else {
                    //LogError
                    return (ReturnType) 0;
                }
            }
        }

        /** \todo Please doc me! */
        void Print( std::ostream &out ) const
        {
            assert( status_ );
            for (MapType::const_iterator it = parameter_map_.begin(); parameter_map_.end() != it; ++it){
                out << it->first << ":" << it->second << "\n" ;
            }
            out << std::endl;
        }

        /** \todo Please doc me! */
        bool Ok()
        {
            return status_;
        }

        /** \todo Please doc me! */
        ~ParameterHandler(){}

};

///** \brief global singelton for paramhandler

ParameterHandler& params()
{
    static ParameterHandler param;
    return param;
}

#endif // PARAMETERHANDLER_HH_INCLUDED
<commit_msg>remove obsolete file<commit_after><|endoftext|>


<commit_before>#ifndef CLOVER_UTIL_PROFILING_HPP
#define CLOVER_UTIL_PROFILING_HPP

#include "build.hpp"
#include "util/preproc_join.hpp"

#include <thread>

// No profiling on windows due to odd crashes with mingw 4.8.2
#define PROFILING_ENABLED (ATOMIC_PTR_READWRITE == true && OS != OS_WINDOWS)

namespace clover {
namespace util {
namespace detail {

struct BlockInfo {
	const char* funcName;
	uint32 line;
	/// Don't assume that labels with same string will point to
	/// the same memory - depends on compiler optimizations
	const char* label;
	uint64 exclusiveMemAllocs;
	uint64 inclusiveMemAllocs;
};

struct BlockProfiler {
	static BlockInfo createBlockInfo(	const char* func,
										uint32 line,
										const char* label);
	BlockProfiler(BlockInfo& info);
	~BlockProfiler();
};

struct StackJoiner {
	StackJoiner();
	~StackJoiner();
};

struct StackDetacher {
	StackDetacher();
	~StackDetacher();
};

void setSuperThread(std::thread::id super_id);

} // detail

/// Call in main() -- we don't want to see any impl defined pre-main stuff
void tryEnableProfiling();

#if PROFILING_ENABLED
/// Should be called on system memory allocation
void profileSystemMemAlloc();
#else
void profileSystemMemAlloc() {};
#endif

} // util
} // clover

#if PROFILING_ENABLED

/// Same as PROFILE but with a label
#define PROFILE_(label)\
	static util::detail::BlockInfo JOIN(profiler_block_info_, __LINE__)= \
		util::detail::BlockProfiler::createBlockInfo( \
				__PRETTY_FUNCTION__, \
				__LINE__, \
				label); \
	util::detail::BlockProfiler JOIN(profiler_, __LINE__)(JOIN(profiler_block_info_, __LINE__))

/// Marks current block to be profiled
#define PROFILE()\
	PROFILE_(nullptr)

/// Notifies profiler of a super thread
#define PROFILER_SUPER_THREAD(thread_id)\
	util::detail::setSuperThread(thread_id)

/// Joins callstacks of this and super thread in current scope
#define PROFILER_STACK_JOIN()\
	util::detail::StackJoiner JOIN(stack_joiner_, __LINE__)
/// Detaches callstacks of this and super thread in current scope
#define PROFILER_STACK_DETACH()\
	util::detail::StackDetacher JOIN(stack_detacher_, __LINE__)

#else

#define PROFILE_(label)
#define PROFILE()
#define PROFILER_SUPER_THREAD(thread_id)
#define PROFILER_STACK_JOIN()
#define PROFILER_STACK_DETACH()

#endif

#endif // CLOVER_UTIL_PROFILING_HPP
<commit_msg>Profiling is now working on windows?!<commit_after>#ifndef CLOVER_UTIL_PROFILING_HPP
#define CLOVER_UTIL_PROFILING_HPP

#include "build.hpp"
#include "util/preproc_join.hpp"

#include <thread>

// No profiling on windows due to odd crashes with mingw 4.8.2
#define PROFILING_ENABLED (ATOMIC_PTR_READWRITE == true)

namespace clover {
namespace util {
namespace detail {

struct BlockInfo {
	const char* funcName;
	uint32 line;
	/// Don't assume that labels with same string will point to
	/// the same memory - depends on compiler optimizations
	const char* label;
	uint64 exclusiveMemAllocs;
	uint64 inclusiveMemAllocs;
};

struct BlockProfiler {
	static BlockInfo createBlockInfo(	const char* func,
										uint32 line,
										const char* label);
	BlockProfiler(BlockInfo& info);
	~BlockProfiler();
};

struct StackJoiner {
	StackJoiner();
	~StackJoiner();
};

struct StackDetacher {
	StackDetacher();
	~StackDetacher();
};

void setSuperThread(std::thread::id super_id);

} // detail

/// Call in main() -- we don't want to see any impl defined pre-main stuff
void tryEnableProfiling();

#if PROFILING_ENABLED
/// Should be called on system memory allocation
void profileSystemMemAlloc();
#else
void profileSystemMemAlloc() {};
#endif

} // util
} // clover

#if PROFILING_ENABLED

/// Same as PROFILE but with a label
#define PROFILE_(label)\
	static util::detail::BlockInfo JOIN(profiler_block_info_, __LINE__)= \
		util::detail::BlockProfiler::createBlockInfo( \
				__PRETTY_FUNCTION__, \
				__LINE__, \
				label); \
	util::detail::BlockProfiler JOIN(profiler_, __LINE__)(JOIN(profiler_block_info_, __LINE__))

/// Marks current block to be profiled
#define PROFILE()\
	PROFILE_(nullptr)

/// Notifies profiler of a super thread
#define PROFILER_SUPER_THREAD(thread_id)\
	util::detail::setSuperThread(thread_id)

/// Joins callstacks of this and super thread in current scope
#define PROFILER_STACK_JOIN()\
	util::detail::StackJoiner JOIN(stack_joiner_, __LINE__)
/// Detaches callstacks of this and super thread in current scope
#define PROFILER_STACK_DETACH()\
	util::detail::StackDetacher JOIN(stack_detacher_, __LINE__)

#else

#define PROFILE_(label)
#define PROFILE()
#define PROFILER_SUPER_THREAD(thread_id)
#define PROFILER_STACK_JOIN()
#define PROFILER_STACK_DETACH()

#endif

#endif // CLOVER_UTIL_PROFILING_HPP
<|endoftext|>


<commit_before>#include <Refal2.h>

namespace Refal2 {

//-----------------------------------------------------------------------------
// CProgram

CProgram::CProgram( int numberOfModules ) :
	modulesSize( numberOfModules ),
	modules( new CRuntimeModule[modulesSize] ),
	emptyFunction( new CEmptyFunction )
{
	assert( modulesSize > 0 );
	assert( modules != nullptr );
}

CProgram::~CProgram()
{
	delete[] modules;
}

CRuntimeModule& CProgram::Module( TRuntimeModuleId moduleId )
{
	assert( moduleId >= 0 && moduleId < modulesSize );
	return modules[moduleId];
}

//-----------------------------------------------------------------------------
// CProgramPrintHelper

void CProgramPrintHelper::Label( std::ostream& outputStream,
	const TLabel label ) const
{
	const int labelModuleId = label / LabelMask;
	if( PrintLabelWithModule() ) {
		outputStream << labelModuleId << ":";
	}
	outputStream << program->Module( labelModuleId ).Functions.
		GetKey(	label % LabelMask );
}

//-----------------------------------------------------------------------------
// CGlobalFunctionData

class CGlobalFunctionData {
public:
	CGlobalFunctionData();

	bool IsEmbeddedFunction() const;
	bool IsPreparatoryFunction() const;
	bool IsDefined() const;

	void SetPreparatoryFunction(
		const CPreparatoryFunction* const _preparatoryFunction,
		const TRuntimeModuleId _runtimeModuleId );
	const CPreparatoryFunction* PreparatoryFunction() const;

	const TRuntimeModuleId RuntimeModuleId() const;

	void SetEmbeddedFunction( const TEmbeddedFunctionPtr _embeddedFunction );
	TEmbeddedFunctionPtr EmbeddedFunction() const;

	CRuntimeFunctionPtr RuntimeFunction( const CProgramPtr& program ) const;

private:
	const CPreparatoryFunction* preparatoryFunction;
	TEmbeddedFunctionPtr embeddedFunction;
	TRuntimeModuleId runtimeModuleId;
	mutable CRuntimeFunctionPtr runtimeFunction;
};

//-----------------------------------------------------------------------------
// CGlobalFunctionData

CGlobalFunctionData::CGlobalFunctionData() :
	preparatoryFunction( nullptr ),
	embeddedFunction( nullptr ),
	runtimeModuleId( 0 )
{
}

bool CGlobalFunctionData::IsEmbeddedFunction() const
{
	return ( embeddedFunction != nullptr );
}

bool CGlobalFunctionData::IsPreparatoryFunction() const
{
	return ( preparatoryFunction != nullptr );
}

bool CGlobalFunctionData::IsDefined() const
{
	return ( IsEmbeddedFunction() || IsPreparatoryFunction() );
}

void CGlobalFunctionData::SetPreparatoryFunction(
	const CPreparatoryFunction* const _preparatoryFunction,
	const TRuntimeModuleId _runtimeModuleId )
{
	assert( !IsDefined() );
	assert( _preparatoryFunction != nullptr );
	preparatoryFunction = _preparatoryFunction;
	runtimeModuleId = _runtimeModuleId;
}

const CPreparatoryFunction* CGlobalFunctionData::PreparatoryFunction() const
{
	assert( IsPreparatoryFunction() );
	return preparatoryFunction;
}

const TRuntimeModuleId CGlobalFunctionData::RuntimeModuleId() const
{
	assert( IsPreparatoryFunction() );
	return runtimeModuleId;
}

void CGlobalFunctionData::SetEmbeddedFunction(
	const TEmbeddedFunctionPtr _embeddedFunction )
{
	assert( !IsDefined() );
	assert( _embeddedFunction != nullptr );
	embeddedFunction = _embeddedFunction;
}

TEmbeddedFunctionPtr CGlobalFunctionData::EmbeddedFunction() const
{
	assert( IsEmbeddedFunction() );
	return embeddedFunction;
}

CRuntimeFunctionPtr CGlobalFunctionData::RuntimeFunction(
	const CProgramPtr& program ) const
{
	if( !static_cast<bool>( runtimeFunction ) ) {
		if( IsEmbeddedFunction() ) {
			runtimeFunction.reset( new CEmbeddedFunction(
				embeddedFunction ) );
		} else {
			assert( IsPreparatoryFunction() );
			if( PreparatoryFunction()->IsEmpty() ) {
				runtimeFunction = program->EmptyFunction();
			} else {
				runtimeFunction.reset( new COrdinaryFunction(
					PreparatoryFunction()->FirstOperation(),
					RuntimeModuleId() ) );
			}
		}
	}
	return runtimeFunction;
}

//-----------------------------------------------------------------------------
// CInternalProgramBuilder

const char* const ProgramStartFunctionName = "go";

class CInternalProgramBuilder {
public:
	static CProgramPtr Build( CModuleDataVector& modules,
		CErrorsHelper& errors );

private:
	CErrorsHelper& errors;
	CDictionary<CGlobalFunctionData, std::string> globals;
	CProgramPtr program;

	CInternalProgramBuilder( CErrorsHelper& _errors, int numberOfModules );

	typedef void ( CInternalProgramBuilder::*TProcessFunctionPtr )(
		CPreparatoryFunction* function,
		const TRuntimeModuleId runtimeModuleId );

	void processModules( const CModuleDataVector& modules,
		const TProcessFunctionPtr processFunction );

	void collectFunction( CPreparatoryFunction* function,
		 const TRuntimeModuleId runtimeModuleId );
	void collect( const CModuleDataVector& modules );

	void check();

	void compileFunction( CPreparatoryFunction* function,
		const TRuntimeModuleId runtimeModuleId );
	void compile( const CModuleDataVector& modules );

	void linkFunction( CPreparatoryFunction* function,
		const TRuntimeModuleId runtimeModuleId );
	void link( const CModuleDataVector& modules );
};

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

CInternalProgramBuilder::CInternalProgramBuilder( CErrorsHelper& _errors,
		int numberOfModules ) :
	errors( _errors ),
	program( new CProgram( numberOfModules ) )
{
	assert( static_cast<bool>( program ) );
	// add standart functions
	for( const CEmbeddedFunctionData* function = EmbeddedFunctionDataTable();
		function->EmbeddedFunction != nullptr; function++ )
	{
		assert( function->ExternalName != nullptr );
		std::string externalName = function->ExternalName;
		assert( !externalName.empty() );
		const int globalIndex = globals.AddKey( externalName );
		CGlobalFunctionData& global = globals.GetData( globalIndex );
		global.SetEmbeddedFunction( function->EmbeddedFunction );
	}
	// add `ProgramStartFunctionName`
	const int globalGoIndex = globals.AddKey( ProgramStartFunctionName );
	assert( !globals.GetData( globalGoIndex ).IsDefined() );
}

CProgramPtr CInternalProgramBuilder::Build( CModuleDataVector& modules,
	CErrorsHelper& errors )
{
	assert( !errors.HasErrors() );
	assert( !modules.empty() );
	CInternalProgramBuilder builder( errors, modules.size() );
	builder.collect( modules );
	if( !errors.HasErrors() ) {
		builder.check();
		if( !errors.HasErrors() ) {
			builder.compile( modules );
			assert( !errors.HasErrors() );
			builder.link( modules );
			assert( !errors.HasErrors() );
			return builder.program;
		}
	}
	modules.clear();
	return nullptr;
}

void CInternalProgramBuilder::processModules( const CModuleDataVector& modules,
	const TProcessFunctionPtr processFunction )
{
	TRuntimeModuleId currentModuleId = 0;
	for( CModuleDataVector::const_iterator module = modules.begin();
		module != modules.end(); ++module )
	{
		const CPreparatoryFunctions& functions = ( *module )->Functions;
		for( int i = 0; i < functions.Size(); i++ ) {
			( this->*processFunction )( functions.GetData( i ).get(),
				currentModuleId );
		}
		currentModuleId++;
	}
}

void CInternalProgramBuilder::collectFunction( CPreparatoryFunction* function,
	const TRuntimeModuleId runtimeModuleId )
{
	if( !function->IsExternal() && !function->IsEntry() ) {
		return;
	}

	const int globalIndex = globals.AddKey( function->ExternalName() );
	if( function->IsEntry() ) {
		assert( !function->IsExternal() );
		CGlobalFunctionData& global = globals.GetData( globalIndex );
		if( global.IsDefined() ) {
			std::ostringstream stringStream;
			stringStream << "function with external name `"
				<< function->ExternalNameToken().word
				<< "` already defined in program";
			errors.RaiseError( ES_LinkError, stringStream.str() );
		} else {
			global.SetPreparatoryFunction( function, runtimeModuleId );
		}
	}
}

void CInternalProgramBuilder::collect( const CModuleDataVector& modules )
{
	processModules( modules, &CInternalProgramBuilder::collectFunction );
}

void CInternalProgramBuilder::check()
{
	for( int globalIndex = 0; globalIndex < globals.Size(); globalIndex++ )
	{
		if( !globals.GetData( globalIndex ).IsDefined() ) {
			std::ostringstream stringStream;
			stringStream << "function with external name `"
				<< globals.GetKey( globalIndex ) << "` was not defined";
			errors.RaiseError( ES_LinkError, stringStream.str() );
		}
	}
}

void CInternalProgramBuilder::compileFunction( CPreparatoryFunction* function,
	const TRuntimeModuleId /*runtimeModuleId*/ )
{
	CFunctionCompiler compiler( program->OperationsHolder() );
	if( function->IsOrdinary() ) {
		DEBUG_PRINT( __FUNCTION__ << " " << function->Name() )
		function->Compile( compiler );
	}
}

void CInternalProgramBuilder::compile( const CModuleDataVector& modules )
{
	processModules( modules, &CInternalProgramBuilder::compileFunction );
}

void CInternalProgramBuilder::linkFunction( CPreparatoryFunction* function,
	const TRuntimeModuleId runtimeModuleId )
{
	CRuntimeFunctions& functions = program->Module( runtimeModuleId ).Functions;
	const int functionKey = functions.AddKey( function->Name() );
	CRuntimeFunctionPtr& runtimeFunction = functions.GetData( functionKey );
	assert( !static_cast<bool>( runtimeFunction ) );

	switch( function->GetType() ) {
		case PFT_Empty:
			runtimeFunction = program->EmptyFunction();
			break;
		case PFT_Compiled:
			runtimeFunction.reset( new COrdinaryFunction(
				function->FirstOperation(), runtimeModuleId ) );
			break;
		case PFT_External:
		{
			const int globalIndex = globals.FindKey( function->ExternalName() );
			assert( globalIndex != InvalidDictionaryIndex );
			const CGlobalFunctionData& global = globals.GetData( globalIndex );
			runtimeFunction = global.RuntimeFunction( program );
			break;
		}
		default:
			assert( false );
			break;
	}
}

void CInternalProgramBuilder::link( const CModuleDataVector& modules )
{
	const CGlobalFunctionData& goFunction = globals.GetData( globals.FindKey(
		ProgramStartFunctionName ) );
	TOperationAddress goFirstOperation =
		goFunction.PreparatoryFunction()->FirstOperation();
	TRuntimeModuleId goRuntimeModuleId = goFunction.RuntimeModuleId();
	// link all
	processModules( modules, &CInternalProgramBuilder::linkFunction );
	// set program start function
	const CRuntimeFunctions& runtimeFunctions =
		program->Module( goRuntimeModuleId ).Functions;
	TLabel goLabel = InvalidDictionaryIndex;
	for( int i = 0; i < runtimeFunctions.Size(); i++ ) {
		if( runtimeFunctions.GetData( i )->IsOrdinary()
			&& static_cast<const COrdinaryFunction*>(
				runtimeFunctions.GetData( i ).get() )->FirstOperation() ==
				goFirstOperation )
		{
			goLabel = i;
		}
	}
	assert( goLabel != InvalidDictionaryIndex );
	program->SetProgramStartFunction( goLabel + goRuntimeModuleId * LabelMask );
}

//-----------------------------------------------------------------------------
// CProgramBuilder

CProgramBuilder::CProgramBuilder( IErrorHandler* errorHandler ) :
	CFunctionBuilder( errorHandler )
{
	Reset();
}

void CProgramBuilder::Reset()
{
	CFunctionBuilder::Reset();
}

void CProgramBuilder::AddModule( CModuleDataPtr& module )
{
	modules.push_back( CModuleDataPtr( module.release() ) );
}

CProgramPtr CProgramBuilder::BuildProgram()
{
	return CInternalProgramBuilder::Build( modules, *this );
}

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

} // end of namespace Refal2
<commit_msg>bug fixes<commit_after>#include <Refal2.h>

namespace Refal2 {

//-----------------------------------------------------------------------------
// CProgram

CProgram::CProgram( int numberOfModules ) :
	modulesSize( numberOfModules ),
	modules( new CRuntimeModule[modulesSize] ),
	emptyFunction( new CEmptyFunction )
{
	assert( modulesSize > 0 );
	assert( modules != nullptr );
}

CProgram::~CProgram()
{
	delete[] modules;
}

CRuntimeModule& CProgram::Module( TRuntimeModuleId moduleId )
{
	assert( moduleId >= 0 && moduleId < modulesSize );
	return modules[moduleId];
}

//-----------------------------------------------------------------------------
// CProgramPrintHelper

void CProgramPrintHelper::Label( std::ostream& outputStream,
	const TLabel label ) const
{
	const int labelModuleId = label / LabelMask;
	if( PrintLabelWithModule() ) {
		outputStream << labelModuleId << ":";
	}
	outputStream << program->Module( labelModuleId ).Functions.
		GetKey(	label % LabelMask );
}

//-----------------------------------------------------------------------------
// CGlobalFunctionData

class CGlobalFunctionData {
public:
	CGlobalFunctionData();

	bool IsEmbeddedFunction() const;
	bool IsPreparatoryFunction() const;
	bool IsDefined() const;

	void SetPreparatoryFunction(
		const CPreparatoryFunction* const _preparatoryFunction,
		const TRuntimeModuleId _runtimeModuleId );
	const CPreparatoryFunction* PreparatoryFunction() const;

	const TRuntimeModuleId RuntimeModuleId() const;

	void SetEmbeddedFunction( const TEmbeddedFunctionPtr _embeddedFunction );
	TEmbeddedFunctionPtr EmbeddedFunction() const;

	CRuntimeFunctionPtr RuntimeFunction( const CProgramPtr& program ) const;

private:
	const CPreparatoryFunction* preparatoryFunction;
	TEmbeddedFunctionPtr embeddedFunction;
	TRuntimeModuleId runtimeModuleId;
	mutable CRuntimeFunctionPtr runtimeFunction;
};

//-----------------------------------------------------------------------------
// CGlobalFunctionData

CGlobalFunctionData::CGlobalFunctionData() :
	preparatoryFunction( nullptr ),
	embeddedFunction( nullptr ),
	runtimeModuleId( 0 )
{
}

bool CGlobalFunctionData::IsEmbeddedFunction() const
{
	return ( embeddedFunction != nullptr );
}

bool CGlobalFunctionData::IsPreparatoryFunction() const
{
	return ( preparatoryFunction != nullptr );
}

bool CGlobalFunctionData::IsDefined() const
{
	return ( IsEmbeddedFunction() || IsPreparatoryFunction() );
}

void CGlobalFunctionData::SetPreparatoryFunction(
	const CPreparatoryFunction* const _preparatoryFunction,
	const TRuntimeModuleId _runtimeModuleId )
{
	assert( !IsDefined() );
	assert( _preparatoryFunction != nullptr );
	preparatoryFunction = _preparatoryFunction;
	runtimeModuleId = _runtimeModuleId;
}

const CPreparatoryFunction* CGlobalFunctionData::PreparatoryFunction() const
{
	assert( IsPreparatoryFunction() );
	return preparatoryFunction;
}

const TRuntimeModuleId CGlobalFunctionData::RuntimeModuleId() const
{
	assert( IsPreparatoryFunction() );
	return runtimeModuleId;
}

void CGlobalFunctionData::SetEmbeddedFunction(
	const TEmbeddedFunctionPtr _embeddedFunction )
{
	assert( !IsDefined() );
	assert( _embeddedFunction != nullptr );
	embeddedFunction = _embeddedFunction;
}

TEmbeddedFunctionPtr CGlobalFunctionData::EmbeddedFunction() const
{
	assert( IsEmbeddedFunction() );
	return embeddedFunction;
}

CRuntimeFunctionPtr CGlobalFunctionData::RuntimeFunction(
	const CProgramPtr& program ) const
{
	if( !static_cast<bool>( runtimeFunction ) ) {
		if( IsEmbeddedFunction() ) {
			runtimeFunction.reset( new CEmbeddedFunction(
				embeddedFunction ) );
		} else {
			assert( IsPreparatoryFunction() );
			if( PreparatoryFunction()->IsEmpty() ) {
				runtimeFunction = program->EmptyFunction();
			} else {
				runtimeFunction.reset( new COrdinaryFunction(
					PreparatoryFunction()->FirstOperation(),
					RuntimeModuleId() ) );
			}
		}
	}
	return runtimeFunction;
}

//-----------------------------------------------------------------------------
// CInternalProgramBuilder

const char* const ProgramStartFunctionName = "go";

class CInternalProgramBuilder {
public:
	static CProgramPtr Build( CModuleDataVector& modules,
		CErrorsHelper& errors );

private:
	CErrorsHelper& errors;
	CDictionary<CGlobalFunctionData, std::string> globals;
	CProgramPtr program;

	CInternalProgramBuilder( CErrorsHelper& _errors, int numberOfModules );

	typedef void ( CInternalProgramBuilder::*TProcessFunctionPtr )(
		CPreparatoryFunction* function,
		const TRuntimeModuleId runtimeModuleId );

	void processModules( const CModuleDataVector& modules,
		const TProcessFunctionPtr processFunction );

	void collectFunction( CPreparatoryFunction* function,
		 const TRuntimeModuleId runtimeModuleId );
	void collect( const CModuleDataVector& modules );

	void check();

	void compileFunction( CPreparatoryFunction* function,
		const TRuntimeModuleId runtimeModuleId );
	void compile( const CModuleDataVector& modules );

	void linkFunction( CPreparatoryFunction* function,
		const TRuntimeModuleId runtimeModuleId );
	void link( const CModuleDataVector& modules );
};

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

CInternalProgramBuilder::CInternalProgramBuilder( CErrorsHelper& _errors,
		int numberOfModules ) :
	errors( _errors ),
	program( new CProgram( numberOfModules ) )
{
	assert( static_cast<bool>( program ) );
	// add standart functions
	for( const CEmbeddedFunctionData* function = EmbeddedFunctionDataTable();
		function->EmbeddedFunction != nullptr; function++ )
	{
		assert( function->ExternalName != nullptr );
		std::string externalName = function->ExternalName;
		assert( !externalName.empty() );
		const int globalIndex = globals.AddKey( externalName );
		CGlobalFunctionData& global = globals.GetData( globalIndex );
		global.SetEmbeddedFunction( function->EmbeddedFunction );
	}
	// add `ProgramStartFunctionName`
	const int globalGoIndex = globals.AddKey( ProgramStartFunctionName );
	assert( !globals.GetData( globalGoIndex ).IsDefined() );
}

CProgramPtr CInternalProgramBuilder::Build( CModuleDataVector& modules,
	CErrorsHelper& errors )
{
	if( !errors.HasErrors() && !modules.empty() ) {
		CInternalProgramBuilder builder( errors, modules.size() );
		builder.collect( modules );
		if( !errors.HasErrors() ) {
			builder.check();
			if( !errors.HasErrors() ) {
				builder.compile( modules );
				assert( !errors.HasErrors() );
				builder.link( modules );
				assert( !errors.HasErrors() );
				return builder.program;
			}
		}
	}
	modules.clear();
	return nullptr;
}

void CInternalProgramBuilder::processModules( const CModuleDataVector& modules,
	const TProcessFunctionPtr processFunction )
{
	TRuntimeModuleId currentModuleId = 0;
	for( CModuleDataVector::const_iterator module = modules.begin();
		module != modules.end(); ++module )
	{
		const CPreparatoryFunctions& functions = ( *module )->Functions;
		for( int i = 0; i < functions.Size(); i++ ) {
			( this->*processFunction )( functions.GetData( i ).get(),
				currentModuleId );
		}
		currentModuleId++;
	}
}

void CInternalProgramBuilder::collectFunction( CPreparatoryFunction* function,
	const TRuntimeModuleId runtimeModuleId )
{
	if( !function->IsExternal() && !function->IsEntry() ) {
		return;
	}

	const int globalIndex = globals.AddKey( function->ExternalName() );
	if( function->IsEntry() ) {
		assert( !function->IsExternal() );
		CGlobalFunctionData& global = globals.GetData( globalIndex );
		if( global.IsDefined() ) {
			std::ostringstream stringStream;
			stringStream << "function with external name `"
				<< function->ExternalNameToken().word
				<< "` already defined in program";
			errors.RaiseError( ES_LinkError, stringStream.str() );
		} else {
			global.SetPreparatoryFunction( function, runtimeModuleId );
		}
	}
}

void CInternalProgramBuilder::collect( const CModuleDataVector& modules )
{
	processModules( modules, &CInternalProgramBuilder::collectFunction );
}

void CInternalProgramBuilder::check()
{
	for( int globalIndex = 0; globalIndex < globals.Size(); globalIndex++ )
	{
		if( !globals.GetData( globalIndex ).IsDefined() ) {
			std::ostringstream stringStream;
			stringStream << "function with external name `"
				<< globals.GetKey( globalIndex ) << "` was not defined";
			errors.RaiseError( ES_LinkError, stringStream.str() );
		}
	}
}

void CInternalProgramBuilder::compileFunction( CPreparatoryFunction* function,
	const TRuntimeModuleId /*runtimeModuleId*/ )
{
	CFunctionCompiler compiler( program->OperationsHolder() );
	if( function->IsOrdinary() ) {
		DEBUG_PRINT( __FUNCTION__ << " " << function->Name() )
		function->Compile( compiler );
	}
}

void CInternalProgramBuilder::compile( const CModuleDataVector& modules )
{
	processModules( modules, &CInternalProgramBuilder::compileFunction );
}

void CInternalProgramBuilder::linkFunction( CPreparatoryFunction* function,
	const TRuntimeModuleId runtimeModuleId )
{
	CRuntimeFunctions& functions = program->Module( runtimeModuleId ).Functions;
	const int functionKey = functions.AddKey( function->Name() );
	CRuntimeFunctionPtr& runtimeFunction = functions.GetData( functionKey );
	assert( !static_cast<bool>( runtimeFunction ) );

	switch( function->GetType() ) {
		case PFT_Empty:
			runtimeFunction = program->EmptyFunction();
			break;
		case PFT_Compiled:
			runtimeFunction.reset( new COrdinaryFunction(
				function->FirstOperation(), runtimeModuleId ) );
			break;
		case PFT_External:
		{
			const int globalIndex = globals.FindKey( function->ExternalName() );
			assert( globalIndex != InvalidDictionaryIndex );
			const CGlobalFunctionData& global = globals.GetData( globalIndex );
			runtimeFunction = global.RuntimeFunction( program );
			break;
		}
		default:
			assert( false );
			break;
	}
}

void CInternalProgramBuilder::link( const CModuleDataVector& modules )
{
	const CGlobalFunctionData& goFunction = globals.GetData( globals.FindKey(
		ProgramStartFunctionName ) );
	TOperationAddress goFirstOperation =
		goFunction.PreparatoryFunction()->FirstOperation();
	TRuntimeModuleId goRuntimeModuleId = goFunction.RuntimeModuleId();
	// link all
	processModules( modules, &CInternalProgramBuilder::linkFunction );
	// set program start function
	const CRuntimeFunctions& runtimeFunctions =
		program->Module( goRuntimeModuleId ).Functions;
	TLabel goLabel = InvalidDictionaryIndex;
	for( int i = 0; i < runtimeFunctions.Size(); i++ ) {
		if( runtimeFunctions.GetData( i )->IsOrdinary()
			&& static_cast<const COrdinaryFunction*>(
				runtimeFunctions.GetData( i ).get() )->FirstOperation() ==
				goFirstOperation )
		{
			goLabel = i;
		}
	}
	assert( goLabel != InvalidDictionaryIndex );
	program->SetProgramStartFunction( goLabel + goRuntimeModuleId * LabelMask );
}

//-----------------------------------------------------------------------------
// CProgramBuilder

CProgramBuilder::CProgramBuilder( IErrorHandler* errorHandler ) :
	CFunctionBuilder( errorHandler )
{
	Reset();
}

void CProgramBuilder::Reset()
{
	CFunctionBuilder::Reset();
}

void CProgramBuilder::AddModule( CModuleDataPtr& module )
{
	modules.push_back( CModuleDataPtr( module.release() ) );
}

CProgramPtr CProgramBuilder::BuildProgram()
{
	return CInternalProgramBuilder::Build( modules, *this );
}

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

} // end of namespace Refal2
<|endoftext|>


<commit_before>#include <sstream>
#include <iostream>
#include <fstream>
#include <vector>

#include <boost/program_options.hpp>
#include <boost/program_options/variables_map.hpp>

#include "filelib.h"
#include "stringlib.h"
#include "sparse_vector.h"
#include "scorer.h"
#include "viterbi_envelope.h"
#include "inside_outside.h"
#include "error_surface.h"
#include "hg.h"
#include "hg_io.h"

using namespace std;
namespace po = boost::program_options;

void InitCommandLine(int argc, char** argv, po::variables_map* conf) {
  po::options_description opts("Configuration options");
  opts.add_options()
        ("reference,r",po::value<vector<string> >(), "[REQD] Reference translation (tokenized text)")
        ("source,s",po::value<string>(), "Source file (ignored, except for AER)")
        ("loss_function,l",po::value<string>()->default_value("ibm_bleu"), "Loss function being optimized")
    ("input,i",po::value<string>()->default_value("-"), "Input file to map (- is STDIN)")
        ("help,h", "Help");
  po::options_description dcmdline_options;
  dcmdline_options.add(opts);
  po::store(parse_command_line(argc, argv, dcmdline_options), *conf);
  bool flag = false;
  if (!conf->count("reference")) {
    cerr << "Please specify one or more references using -r <REF.TXT>\n";
    flag = true;
  }
  if (flag || conf->count("help")) {
    cerr << dcmdline_options << endl;
    exit(1);
  }
}

bool ReadSparseVectorString(const string& s, SparseVector<double>* v) {
  vector<string> fields;
  Tokenize(s, ';', &fields);
  if (fields.empty()) return false;
  for (int i = 0; i < fields.size(); ++i) {
    vector<string> pair(2);
    Tokenize(fields[i], '=', &pair);
    if (pair.size() != 2) {
      cerr << "Error parsing vector string: " << fields[i] << endl;
      return false;
    }
    v->set_value(FD::Convert(pair[0]), atof(pair[1].c_str()));
  }
  return true;
}

int main(int argc, char** argv) {
  po::variables_map conf;
  InitCommandLine(argc, argv, &conf);
  const string loss_function = conf["loss_function"].as<string>();
  ScoreType type = ScoreTypeFromString(loss_function);
  DocScorer ds(type, conf["reference"].as<vector<string> >(), conf["source"].as<string>());
  cerr << "Loaded " << ds.size() << " references for scoring with " << loss_function << endl;
  Hypergraph hg;
  string last_file;
  ReadFile in_read(conf["input"].as<string>());
  istream &in=*in_read.stream();
  while(in) {
    string line;
    getline(in, line);
    if (line.empty()) continue;
    istringstream is(line);
    int sent_id;
    string file, s_origin, s_axis;
    is >> file >> sent_id >> s_origin >> s_axis;
    SparseVector<double> origin;
    assert(ReadSparseVectorString(s_origin, &origin));
    SparseVector<double> axis;
    assert(ReadSparseVectorString(s_axis, &axis));
    // cerr << "File: " << file << "\nAxis: " << axis << "\n   X: " << origin << endl;
    if (last_file != file) {
      last_file = file;
      ReadFile rf(file);
      HypergraphIO::ReadFromJSON(rf.stream(), &hg);
    }
    ViterbiEnvelopeWeightFunction wf(origin, axis);
    ViterbiEnvelope ve = Inside<ViterbiEnvelope, ViterbiEnvelopeWeightFunction>(hg, NULL, wf);
    ErrorSurface es;
    ds[sent_id]->ComputeErrorSurface(ve, &es, type, hg);
    //cerr << "Viterbi envelope has " << ve.size() << " segments\n";
    // cerr << "Error surface has " << es.size() << " segments\n";
    string val;
    es.Serialize(&val);
    cout << 'M' << ' ' << s_origin << ' ' << s_axis << '\t';
    B64::b64encode(val.c_str(), val.size(), &cout);
    cout << endl;
  }
  return 0;
}
<commit_msg>whitespace<commit_after>#include <sstream>
#include <iostream>
#include <fstream>
#include <vector>

#include <boost/program_options.hpp>
#include <boost/program_options/variables_map.hpp>

#include "filelib.h"
#include "stringlib.h"
#include "sparse_vector.h"
#include "scorer.h"
#include "viterbi_envelope.h"
#include "inside_outside.h"
#include "error_surface.h"
#include "hg.h"
#include "hg_io.h"

using namespace std;
namespace po = boost::program_options;

void InitCommandLine(int argc, char** argv, po::variables_map* conf) {
  po::options_description opts("Configuration options");
  opts.add_options()
        ("reference,r",po::value<vector<string> >(), "[REQD] Reference translation (tokenized text)")
        ("source,s",po::value<string>(), "Source file (ignored, except for AER)")
        ("loss_function,l",po::value<string>()->default_value("ibm_bleu"), "Loss function being optimized")
        ("input,i",po::value<string>()->default_value("-"), "Input file to map (- is STDIN)")
        ("help,h", "Help");
  po::options_description dcmdline_options;
  dcmdline_options.add(opts);
  po::store(parse_command_line(argc, argv, dcmdline_options), *conf);
  bool flag = false;
  if (!conf->count("reference")) {
    cerr << "Please specify one or more references using -r <REF.TXT>\n";
    flag = true;
  }
  if (flag || conf->count("help")) {
    cerr << dcmdline_options << endl;
    exit(1);
  }
}

bool ReadSparseVectorString(const string& s, SparseVector<double>* v) {
  vector<string> fields;
  Tokenize(s, ';', &fields);
  if (fields.empty()) return false;
  for (int i = 0; i < fields.size(); ++i) {
    vector<string> pair(2);
    Tokenize(fields[i], '=', &pair);
    if (pair.size() != 2) {
      cerr << "Error parsing vector string: " << fields[i] << endl;
      return false;
    }
    v->set_value(FD::Convert(pair[0]), atof(pair[1].c_str()));
  }
  return true;
}

int main(int argc, char** argv) {
  po::variables_map conf;
  InitCommandLine(argc, argv, &conf);
  const string loss_function = conf["loss_function"].as<string>();
  ScoreType type = ScoreTypeFromString(loss_function);
  DocScorer ds(type, conf["reference"].as<vector<string> >(), conf["source"].as<string>());
  cerr << "Loaded " << ds.size() << " references for scoring with " << loss_function << endl;
  Hypergraph hg;
  string last_file;
  ReadFile in_read(conf["input"].as<string>());
  istream &in=*in_read.stream();
  while(in) {
    string line;
    getline(in, line);
    if (line.empty()) continue;
    istringstream is(line);
    int sent_id;
    string file, s_origin, s_axis;
    is >> file >> sent_id >> s_origin >> s_axis;
    SparseVector<double> origin;
    assert(ReadSparseVectorString(s_origin, &origin));
    SparseVector<double> axis;
    assert(ReadSparseVectorString(s_axis, &axis));
    // cerr << "File: " << file << "\nAxis: " << axis << "\n   X: " << origin << endl;
    if (last_file != file) {
      last_file = file;
      ReadFile rf(file);
      HypergraphIO::ReadFromJSON(rf.stream(), &hg);
    }
    ViterbiEnvelopeWeightFunction wf(origin, axis);
    ViterbiEnvelope ve = Inside<ViterbiEnvelope, ViterbiEnvelopeWeightFunction>(hg, NULL, wf);
    ErrorSurface es;
    ds[sent_id]->ComputeErrorSurface(ve, &es, type, hg);
    //cerr << "Viterbi envelope has " << ve.size() << " segments\n";
    // cerr << "Error surface has " << es.size() << " segments\n";
    string val;
    es.Serialize(&val);
    cout << 'M' << ' ' << s_origin << ' ' << s_axis << '\t';
    B64::b64encode(val.c_str(), val.size(), &cout);
    cout << endl;
  }
  return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2008-2010 The QXmpp developers
 *
 * Author:
 *  Manjeet Dahiya
 *
 * Source:
 *  http://code.google.com/p/qxmpp
 *
 * This file is a part of QXmpp library.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 */

#include "QXmppUtils.h"
#include "QXmppIq.h"

#include <QDomElement>
#include <QXmlStreamWriter>

/// Constructs a QXmppIq with the specified \a type.
///
/// \param type

QXmppIq::QXmppIq(QXmppIq::Type type)
    : QXmppStanza(), m_type(type)
{
    generateAndSetNextId();
}

/// Returns the IQ's type.
///

QXmppIq::Type QXmppIq::type() const
{
    return m_type;
}

/// Sets the IQ's type.
///
/// \param type

void QXmppIq::setType(QXmppIq::Type type)
{
    m_type = type;
}

void QXmppIq::parse(const QDomElement &element)
{
    QXmppStanza::parse(element);
    setTypeFromStr(element.attribute("type"));
    parseElementFromChild(element);
}

void QXmppIq::parseElementFromChild(const QDomElement &element)
{
    QXmppElementList extensions;
    QDomElement itemElement = element.firstChildElement();
    while (!itemElement.isNull())
    {
        extensions.append(QXmppElement(itemElement));
        itemElement = itemElement.nextSiblingElement();
    }
    setExtensions(extensions);
}

void QXmppIq::toXml( QXmlStreamWriter *xmlWriter ) const
{
    xmlWriter->writeStartElement("iq");

    helperToXmlAddAttribute(xmlWriter, "id", id());
    helperToXmlAddAttribute(xmlWriter, "to", to());
    helperToXmlAddAttribute(xmlWriter, "from", from());
    if(getTypeStr().isEmpty())
        helperToXmlAddAttribute(xmlWriter, "type", "get");
    else
        helperToXmlAddAttribute(xmlWriter,  "type", getTypeStr());
    toXmlElementFromChild(xmlWriter);
    error().toXml(xmlWriter);
    xmlWriter->writeEndElement();
}

void QXmppIq::toXmlElementFromChild( QXmlStreamWriter *writer ) const
{
    foreach (const QXmppElement &extension, extensions())
        extension.toXml(writer);
}

QString QXmppIq::getTypeStr() const
{
    switch(m_type)
    {
    case QXmppIq::Error:
        return "error";
    case QXmppIq::Get:
        return "get";
    case QXmppIq::Set:
        return "set";
    case QXmppIq::Result:
        return "result";
    default:
        qWarning("QXmppIq::getTypeStr() invalid type %d", (int)m_type);
        return "";
    }
}

void QXmppIq::setTypeFromStr(const QString& str)
{
    if(str == "error")
    {
        setType(QXmppIq::Error);
        return;
    }
    else if(str == "get")
    {
        setType(QXmppIq::Get);
        return;
    }
    else if(str == "set")
    {
        setType(QXmppIq::Set);
        return;
    }
    else if(str == "result")
    {
        setType(QXmppIq::Result);
        return;
    }
    else
    {
        setType(static_cast<QXmppIq::Type>(-1));
        qWarning("QXmppIq::setTypeFromStr() invalid input string type: %s",
                 qPrintable(str));
        return;
    }
}

// deprecated

QXmppIq::Type QXmppIq::getType() const
{
    return m_type;
}

<commit_msg>doc improvement<commit_after>/*
 * Copyright (C) 2008-2010 The QXmpp developers
 *
 * Author:
 *  Manjeet Dahiya
 *
 * Source:
 *  http://code.google.com/p/qxmpp
 *
 * This file is a part of QXmpp library.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 */

#include "QXmppUtils.h"
#include "QXmppIq.h"

#include <QDomElement>
#include <QXmlStreamWriter>

/// Constructs a QXmppIq with the specified \a type.
///
/// \param type

QXmppIq::QXmppIq(QXmppIq::Type type)
    : QXmppStanza(), m_type(type)
{
    generateAndSetNextId();
}

/// Returns the IQ's type.
///
/// \return QXmppIq::Type

QXmppIq::Type QXmppIq::type() const
{
    return m_type;
}

/// Sets the IQ's type.
///
/// \param type as QXmppIq::Type

void QXmppIq::setType(QXmppIq::Type type)
{
    m_type = type;
}

void QXmppIq::parse(const QDomElement &element)
{
    QXmppStanza::parse(element);
    setTypeFromStr(element.attribute("type"));
    parseElementFromChild(element);
}

void QXmppIq::parseElementFromChild(const QDomElement &element)
{
    QXmppElementList extensions;
    QDomElement itemElement = element.firstChildElement();
    while (!itemElement.isNull())
    {
        extensions.append(QXmppElement(itemElement));
        itemElement = itemElement.nextSiblingElement();
    }
    setExtensions(extensions);
}

void QXmppIq::toXml( QXmlStreamWriter *xmlWriter ) const
{
    xmlWriter->writeStartElement("iq");

    helperToXmlAddAttribute(xmlWriter, "id", id());
    helperToXmlAddAttribute(xmlWriter, "to", to());
    helperToXmlAddAttribute(xmlWriter, "from", from());
    if(getTypeStr().isEmpty())
        helperToXmlAddAttribute(xmlWriter, "type", "get");
    else
        helperToXmlAddAttribute(xmlWriter,  "type", getTypeStr());
    toXmlElementFromChild(xmlWriter);
    error().toXml(xmlWriter);
    xmlWriter->writeEndElement();
}

void QXmppIq::toXmlElementFromChild( QXmlStreamWriter *writer ) const
{
    foreach (const QXmppElement &extension, extensions())
        extension.toXml(writer);
}

QString QXmppIq::getTypeStr() const
{
    switch(m_type)
    {
    case QXmppIq::Error:
        return "error";
    case QXmppIq::Get:
        return "get";
    case QXmppIq::Set:
        return "set";
    case QXmppIq::Result:
        return "result";
    default:
        qWarning("QXmppIq::getTypeStr() invalid type %d", (int)m_type);
        return "";
    }
}

void QXmppIq::setTypeFromStr(const QString& str)
{
    if(str == "error")
    {
        setType(QXmppIq::Error);
        return;
    }
    else if(str == "get")
    {
        setType(QXmppIq::Get);
        return;
    }
    else if(str == "set")
    {
        setType(QXmppIq::Set);
        return;
    }
    else if(str == "result")
    {
        setType(QXmppIq::Result);
        return;
    }
    else
    {
        setType(static_cast<QXmppIq::Type>(-1));
        qWarning("QXmppIq::setTypeFromStr() invalid input string type: %s",
                 qPrintable(str));
        return;
    }
}

// deprecated

QXmppIq::Type QXmppIq::getType() const
{
    return m_type;
}

<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2018.  All rights reserved
 */
#include "../StroikaPreComp.h"

#include "../Time/Duration.h"

#include "Common.h"
#include "TimeOutException.h"

#include "WaitableEvent.h"

using namespace Stroika::Foundation;
using namespace Stroika::Foundation::Execution;

using Stroika::Foundation::Time::Duration;

// Comment this in to turn on aggressive noisy DbgTrace in this module
//#define   USE_NOISY_TRACE_IN_THIS_MODULE_       1

/*
 * Design notes:
 *
 *      o   The use of condition variables is non-obvious. I haven't found good documentation, but
 *          the best I've found would be
 *              https://computing.llnl.gov/tutorials/pthreads/#ConVarOverview
 *
 *          In particular, on the surface, it looks like the mutex locks in Wait() and signal should prevent things
 *          form working (deadlock). But they apparently do not cause a deadlock because
 *              "pthread_cond_wait() blocks the calling thread until the specified condition is signalled.
 *               This routine should be called while mutex is locked, and it will automatically release the
 *               mutex while it waits. After signal is received and thread is awakened, mutex will be
 *               automatically locked for use by the thread. The programmer is then responsible for
 *               unlocking mutex when the thread is finished with it."
 *
 */

/*
 ********************************************************************************
 ****************************** WaitableEvent::WE_ ******************************
 ********************************************************************************
 */
void WaitableEvent::WE_::WaitUntil (Time::DurationSecondsType timeoutAt)
{
    if (WaitUntilQuietly (timeoutAt) == kWaitQuietlyTimeoutResult) {
// note - safe use of TimeOutException::kThe because you cannot really wait except when threads are running, so
// inside 'main' lifetime
#if USE_NOISY_TRACE_IN_THIS_MODULE_
        // only thing Throw() helper does is DbgTrace ()- and that can make traces hard to read unless you are debugging a timeout /event issue
        Throw (TimeOutException::kThe);
#else
        throw (TimeOutException::kThe);
#endif
    }
}

bool WaitableEvent::WE_::WaitUntilQuietly (Time::DurationSecondsType timeoutAt)
{
#if USE_NOISY_TRACE_IN_THIS_MODULE_
    Debug::TraceContextBumper ctx (L"WaitableEvent::WE_::WaitUntil", "timeout = %e", timeoutAt);
#endif
    CheckForThreadInterruption ();
    std::unique_lock<mutex> lock (fConditionVariable.fMutex);
    if (fConditionVariable.wait_until (lock, timeoutAt, [this]() { return fTriggered; })) {
        if (fResetType == eAutoReset) {
            // cannot call Reset () directly because we (may???) already have the lock mutex? Maybe not cuz of cond variable?
            fTriggered = false; // autoreset
        }
        return not kWaitQuietlyTimeoutResult;
    }
    else {
        return kWaitQuietlyTimeoutResult;
    }
}

/*
 ********************************************************************************
 ********************************** WaitableEvent *******************************
 ********************************************************************************
 */
constexpr WaitableEvent::ResetType WaitableEvent::eAutoReset;
constexpr WaitableEvent::ResetType WaitableEvent::eManualReset;

#if qDebug || qStroika_FeatureSupported_Valgrind
WaitableEvent::~WaitableEvent ()
{
    Require (fExtraWaitableEvents_.empty ());                                                      // Cannot kill a waitable event while its being waited on by others
 //   Stroika_Foundation_Debug_ValgrindDisableHelgrind (fWE_.fConditionVariable.fConditionVariable); // avoid sporadic (about 1/3 time) probably spurious helgrind failure - for test Foundation::Execution::Threads -https://stroika.atlassian.net/browse/STK-484
}
#endif

void WaitableEvent::Set ()
{
#if USE_NOISY_TRACE_IN_THIS_MODULE_
    Debug::TraceContextBumper ctx ("WaitableEvent::Set");
#endif
    fWE_.Set ();
#if qExecution_WaitableEvent_SupportWaitForMultipleObjects
    auto critSec{make_unique_lock (_Stroika_Foundation_Execution_Private_WaitableEvent_ModuleInit_.Actual ().fExtraWaitableEventsMutex_)};
    for (auto i : fExtraWaitableEvents_) {
        i->Set ();
    }
#endif
}
<commit_msg>https://stroika.atlassian.net/browse/STK-484 possible fix - waitableevent - may need extra mutex lock on read (found with tsan)<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2018.  All rights reserved
 */
#include "../StroikaPreComp.h"

#include "../Time/Duration.h"

#include "Common.h"
#include "TimeOutException.h"

#include "WaitableEvent.h"

using namespace Stroika::Foundation;
using namespace Stroika::Foundation::Execution;

using Stroika::Foundation::Time::Duration;

// Comment this in to turn on aggressive noisy DbgTrace in this module
//#define   USE_NOISY_TRACE_IN_THIS_MODULE_       1

/*
 * Design notes:
 *
 *      o   The use of condition variables is non-obvious. I haven't found good documentation, but
 *          the best I've found would be
 *              https://computing.llnl.gov/tutorials/pthreads/#ConVarOverview
 *
 *          In particular, on the surface, it looks like the mutex locks in Wait() and signal should prevent things
 *          form working (deadlock). But they apparently do not cause a deadlock because
 *              "pthread_cond_wait() blocks the calling thread until the specified condition is signalled.
 *               This routine should be called while mutex is locked, and it will automatically release the
 *               mutex while it waits. After signal is received and thread is awakened, mutex will be
 *               automatically locked for use by the thread. The programmer is then responsible for
 *               unlocking mutex when the thread is finished with it."
 *
 */

/*
 ********************************************************************************
 ****************************** WaitableEvent::WE_ ******************************
 ********************************************************************************
 */
void WaitableEvent::WE_::WaitUntil (Time::DurationSecondsType timeoutAt)
{
    if (WaitUntilQuietly (timeoutAt) == kWaitQuietlyTimeoutResult) {
// note - safe use of TimeOutException::kThe because you cannot really wait except when threads are running, so
// inside 'main' lifetime
#if USE_NOISY_TRACE_IN_THIS_MODULE_
        // only thing Throw() helper does is DbgTrace ()- and that can make traces hard to read unless you are debugging a timeout /event issue
        Throw (TimeOutException::kThe);
#else
        throw (TimeOutException::kThe);
#endif
    }
}

bool WaitableEvent::WE_::WaitUntilQuietly (Time::DurationSecondsType timeoutAt)
{
#if USE_NOISY_TRACE_IN_THIS_MODULE_
    Debug::TraceContextBumper ctx (L"WaitableEvent::WE_::WaitUntil", "timeout = %e", timeoutAt);
#endif
    CheckForThreadInterruption ();
    std::unique_lock<mutex> lock (fConditionVariable.fMutex);
    if (fConditionVariable.wait_until (lock, timeoutAt, [this]() { return fTriggered; })) {
        if (fResetType == eAutoReset) {
            // cannot call Reset () directly because we (may???) already have the lock mutex? Maybe not cuz of cond variable?
            fTriggered = false; // autoreset
        }
        return not kWaitQuietlyTimeoutResult;
    }
    else {
        return kWaitQuietlyTimeoutResult;
    }
}

/*
 ********************************************************************************
 ********************************** WaitableEvent *******************************
 ********************************************************************************
 */
constexpr WaitableEvent::ResetType WaitableEvent::eAutoReset;
constexpr WaitableEvent::ResetType WaitableEvent::eManualReset;

#if qDebug || qStroika_FeatureSupported_Valgrind
WaitableEvent::~WaitableEvent ()
{
    Require (fExtraWaitableEvents_.empty ()); // Cannot kill a waitable event while its being waited on by others
                                              //   Stroika_Foundation_Debug_ValgrindDisableHelgrind (fWE_.fConditionVariable.fConditionVariable); // avoid sporadic (about 1/3 time) probably spurious helgrind failure - for test Foundation::Execution::Threads -https://stroika.atlassian.net/browse/STK-484
}
#endif

void WaitableEvent::Set ()
{
#if USE_NOISY_TRACE_IN_THIS_MODULE_
    Debug::TraceContextBumper ctx ("WaitableEvent::Set");
#endif
    fWE_.Set ();
#if qExecution_WaitableEvent_SupportWaitForMultipleObjects
    auto critSec{make_unique_lock (_Stroika_Foundation_Execution_Private_WaitableEvent_ModuleInit_.Actual ().fExtraWaitableEventsMutex_)};
    for (auto i : fExtraWaitableEvents_) {
        i->Set ();
    }
#endif
}
<|endoftext|>


<commit_before>//
// This program will take a flow XML and run it in dummy mode.
// This means that it will run every node with a dummy function and
// exercise the flow with all of its guard acquisitions.
// It can be used to test the flow for bottlenecks or other effects.
// It may also indicate interesting effects related to choice of runtime.
// Limitations:
//  * guards are reduced to singleton (no () key guards)
//  * no data is passed since the replacement nodes do not pass inputs or
//     outputs

#include "OFlux.h"
#include "flow/OFluxFlowExerciseFunctions.h"
#include "flow/OFluxFlow.h"
#include "atomic/OFluxAtomic.h"
#include "lockfree/atomic/OFluxLFAtomicMaps.h"
#include "atomic/OFluxAtomicHolder.h"
#include "OFluxRunTimeBase.h"
#include "OFluxIOConversion.h"
#include "OFluxEarlyRelease.h"
#include "OFluxLogging.h"
#include <iostream>
#include <signal.h>

oflux::shared_ptr<oflux::RunTimeAbstract> theRT;

void
init_atomic_maps(int) {}

oflux::flow::exercise::AtomicSetAbstract * atomic_set = NULL;
oflux::flow::Flow * flow = NULL;

void handlesighup(int)
{
	signal(SIGHUP,handlesighup);
	atomic_set->report();
	oflux::flow::exercise::node_report(flow);
	theRT->log_snapshot();
}

oflux::flow::exercise::AtomicAbstract::P * _atomic_array;

void
ex_release_guards()
{
	oflux::release_all_guards(theRT.get());
}

int
main(int argc, char * argv[])
{
	oflux::flow::exercise::release_guards = ex_release_guards;

	if(argc <= 1) {
		std::cout << "provide an XML flow file argument\n";
		return 9;
	}
	char * max_nsec_wait_str = getenv("EXERCISE_SLEEP");
	if(max_nsec_wait_str) {
		oflux::flow::exercise::max_nsec_wait = atol(max_nsec_wait_str);
	}
	int init_threads = 0;
	char * init_threads_str = getenv("EXERCISE_THREADS");
	if(init_threads_str) {
		init_threads = atoi(init_threads_str);
	}
	oflux::RunTimeConfiguration rtc = {
		  1024*1024 // stack size
		, init_threads // initial threads (ignored really)
		, 0 // max threads
		, 0 // max detached
		, 0 // thread collection threshold
		, 1000 // thread collection sample period (every N node execs)
		, argv[1] // XML file
		, NULL // temporary
		, "xml" // xml subdir for plugins
		, "lib" // lib subdir for plugins
		, NULL
		, init_atomic_maps
		};
	oflux::logging::toStream(std::cout);
	oflux_log_info(" exercise::max_nsec_wait is %ld\n", oflux::flow::exercise::max_nsec_wait);
	oflux::EnvironmentVar env(oflux::runtime::Factory::classic);
	oflux::flow::ExerciseFunctionMaps ffmaps(env.runtime_number == 4);
	atomic_set = ffmaps.atomic_set();
	rtc.flow_maps = &ffmaps;
	theRT.reset(oflux::runtime::Factory::create(env.runtime_number, rtc));
	flow = theRT->flow();
	oflux::flow::exercise::AtomicAbstract::P atomic_array[atomic_set->size()+1];
	_atomic_array = &atomic_array[0];
	atomic_set->fill(atomic_array);
	signal(SIGHUP,handlesighup);
	if(!env.nostart) {
		theRT->start();
	}
	theRT.reset(); // force deletion of the runtime

	return 0;
}
<commit_msg>max threads in exercise<commit_after>//
// This program will take a flow XML and run it in dummy mode.
// This means that it will run every node with a dummy function and
// exercise the flow with all of its guard acquisitions.
// It can be used to test the flow for bottlenecks or other effects.
// It may also indicate interesting effects related to choice of runtime.
// Limitations:
//  * guards are reduced to singleton (no () key guards)
//  * no data is passed since the replacement nodes do not pass inputs or
//     outputs

#include "OFlux.h"
#include "flow/OFluxFlowExerciseFunctions.h"
#include "flow/OFluxFlow.h"
#include "atomic/OFluxAtomic.h"
#include "lockfree/atomic/OFluxLFAtomicMaps.h"
#include "atomic/OFluxAtomicHolder.h"
#include "OFluxRunTimeBase.h"
#include "OFluxIOConversion.h"
#include "OFluxEarlyRelease.h"
#include "OFluxLogging.h"
#include <iostream>
#include <signal.h>

oflux::shared_ptr<oflux::RunTimeAbstract> theRT;

void
init_atomic_maps(int) {}

oflux::flow::exercise::AtomicSetAbstract * atomic_set = NULL;
oflux::flow::Flow * flow = NULL;

void handlesighup(int)
{
	signal(SIGHUP,handlesighup);
	atomic_set->report();
	oflux::flow::exercise::node_report(flow);
	theRT->log_snapshot();
}

oflux::flow::exercise::AtomicAbstract::P * _atomic_array;

void
ex_release_guards()
{
	oflux::release_all_guards(theRT.get());
}

int
main(int argc, char * argv[])
{
	oflux::flow::exercise::release_guards = ex_release_guards;

	if(argc <= 1) {
		std::cout << "provide an XML flow file argument\n";
		return 9;
	}
	char * max_nsec_wait_str = getenv("EXERCISE_SLEEP");
	if(max_nsec_wait_str) {
		oflux::flow::exercise::max_nsec_wait = atol(max_nsec_wait_str);
	}
	int init_threads = 0;
	char * init_threads_str = getenv("EXERCISE_THREADS");
	if(init_threads_str) {
		init_threads = atoi(init_threads_str);
	}
	oflux::RunTimeConfiguration rtc = {
		  1024*1024 // stack size
		, init_threads // initial threads (ignored really)
		, 64 // max threads
		, 0 // max detached
		, 0 // thread collection threshold
		, 1000 // thread collection sample period (every N node execs)
		, argv[1] // XML file
		, NULL // temporary
		, "xml" // xml subdir for plugins
		, "lib" // lib subdir for plugins
		, NULL
		, init_atomic_maps
		};
	oflux::logging::toStream(std::cout);
	oflux_log_info(" exercise::max_nsec_wait is %ld\n", oflux::flow::exercise::max_nsec_wait);
	oflux::EnvironmentVar env(oflux::runtime::Factory::classic);
	oflux::flow::ExerciseFunctionMaps ffmaps(env.runtime_number == 4);
	atomic_set = ffmaps.atomic_set();
	rtc.flow_maps = &ffmaps;
	theRT.reset(oflux::runtime::Factory::create(env.runtime_number, rtc));
	flow = theRT->flow();
	oflux::flow::exercise::AtomicAbstract::P atomic_array[atomic_set->size()+1];
	_atomic_array = &atomic_array[0];
	atomic_set->fill(atomic_array);
	signal(SIGHUP,handlesighup);
	if(!env.nostart) {
		theRT->start();
	}
	theRT.reset(); // force deletion of the runtime

	return 0;
}
<|endoftext|>


<commit_before>//
// Copyright 2014, 2015 Razer Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#include "OSVRPrivatePCH.h"

#include "OSVRInterfaceCollection.h"
#include "OSVREntryPoint.h"

OSVR_ClientContext osvrClientContext(nullptr);

OSVREntryPoint::OSVREntryPoint()
{
	osvrClientContext = osvrClientInit("OSVR Unreal Engine 4 Plugin");

	InterfaceCollection = MakeShareable(new OSVRInterfaceCollection(
		osvrClientContext
		));
}

OSVREntryPoint::~OSVREntryPoint()
{
	InterfaceCollection = nullptr;

	osvrClientShutdown(osvrClientContext);
}

void OSVREntryPoint::Tick(float DeltaTime)
{
	osvrClientUpdate(osvrClientContext);
}

OSVRInterfaceCollection* OSVREntryPoint::GetInterfaceCollection()
{
	return InterfaceCollection.Get();
}
<commit_msg>Small change to the application identifier.<commit_after>//
// Copyright 2014, 2015 Razer Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#include "OSVRPrivatePCH.h"

#include "OSVRInterfaceCollection.h"
#include "OSVREntryPoint.h"

OSVR_ClientContext osvrClientContext(nullptr);

OSVREntryPoint::OSVREntryPoint()
{
	osvrClientContext = osvrClientInit("com.osvr.unreal.plugin");

	InterfaceCollection = MakeShareable(new OSVRInterfaceCollection(
		osvrClientContext
		));
}

OSVREntryPoint::~OSVREntryPoint()
{
	InterfaceCollection = nullptr;

	osvrClientShutdown(osvrClientContext);
}

void OSVREntryPoint::Tick(float DeltaTime)
{
	osvrClientUpdate(osvrClientContext);
}

OSVRInterfaceCollection* OSVREntryPoint::GetInterfaceCollection()
{
	return InterfaceCollection.Get();
}
<|endoftext|>


<commit_before>#include <numeric>
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <set>
#include <csignal>
#include <cmath>
#include <ctgmath>

#include "sdd/sdd.hh"
#include "sdd/tools/size.hh"
#include "sdd/tools/nodes.hh"
#include "sdd/tools/arcs.hh"
#include "sdd/tools/sequences.hh"
#include "sdd/tools/dot/sdd.hh"

using namespace std;

static bool finish = false;

void
handler(int s)
{
  finish = true;
}

struct conf
  : public sdd::flat_set_default_configuration
{
  using Identifier = unsigned int;
  using Values     = sdd::values::flat_set<char>;
};
using SDD         = sdd::SDD<conf>;
using values_type = conf::Values;

int
main (int argc, const char** argv)
{
  const auto subsize = 100;
  if (argc == 0)
  {
    cerr << "sdd-stream <max-length>" << endl;
    return 1;
  }

  struct sigaction sigIntHandler;
  sigIntHandler.sa_handler = handler;
  sigemptyset (&sigIntHandler.sa_mask);
  sigIntHandler.sa_flags = 0;
  sigaction (SIGINT, &sigIntHandler, NULL);

  size_t max_length = stoi (argv [1]);

  vector<SDD> collections;
  collections.reserve (subsize);

  conf c;
  c.final_cleanup = false; // don't cleanup memory on manager scope exit.
  c.hom_cache_size = 2; // we don't use homomorphisms.
  c.hom_unique_table_size = 2; // we don't use homomorphisms.
//  c.sdd_intersection_cache_size = 16000000;
//  c.sdd_sum_cache_size = 16000000;
//  c.sdd_difference_cache_size = 16000000;
//  c.sdd_unique_table_size = 10000000;
  auto manager = sdd::init<conf>(c);

  // // Construct the SDD order: we need one level per letter.
  // vector<unsigned int> v (max_length);
  // iota (v.begin(), v.end(), 0);
  sdd::order_builder<conf> ob;
  const sdd::order<conf> order {sdd::order_builder<conf> ()};

  set<char> characters;

  size_t inserted = 0;
  size_t dropped  = 0;
  size_t total    = 0;
  size_t sum_inserted = 0;
  string line;
  line.reserve (80);
  string sequence;
  sequence.reserve (max_length);
  cout << "\033[s" << flush;
  while (getline (cin, line))
  {
    if (line [0] == '>')
    { // starting a new sequence:
      total += 1;
      if (sequence.size () != 0)
      {
        if (sequence.size () <= max_length)
        {
          SDD word = SDD(0, SDD::eol::flat, sdd::one<conf>());
          for (auto i = 0u; i < sequence.size(); ++i)
          {
            characters.insert (sequence[sequence.size() - i - 1]);
            word = SDD(0, {sequence[sequence.size() - i - 1]}, word);
          }
          collections.emplace_back(word);
          inserted += 1;
          sum_inserted += sequence.size();
        }
        else
          dropped += 1;
        sequence.clear ();
      }
      if (finish)
        break;
    }
    else
      sequence += line;
    if (collections.size () == subsize)
    {
      const auto result = sdd::sum<conf> ( collections.cbegin()
                                         , collections.cend() );
      collections.clear ();
      collections.push_back (result);
    }
    if (total % 200 == 0)
      cout << "\033[u"
           << "inserted: " << inserted
           << " / "
           << "dropped: " << dropped
           << " / "
           << "total: " << total
           << flush;
  }
  if (sequence.size () <= max_length)
  {
    SDD word = SDD(0, SDD::eol::flat, sdd::one<conf>());
    for (auto i = 0u; i < line.size(); ++i)
    {
      word = SDD(0, {line[line.size() - i - 1]}, word);
    }
    collections.emplace_back(word);
    inserted += 1;
    sum_inserted += sequence.size();
  }
  else
    dropped += 1;
  cout << "\033[u"
       << "inserted: " << inserted
       << " / "
       << "dropped: " << dropped
       << " / "
       << "total: " << total
       << endl;
  const auto result = sdd::sum<conf> ( collections.cbegin()
                                     , collections.cend() );

  cout << "# Characters: " << characters.size() << endl;
  cout << "# Words: " << result.size() << endl;
  const auto nodes = sdd::tools::nodes(result).first;
  cout << "# Nodes: " << nodes << endl;
  const auto size = sdd::tools::size(result);
  cout << "Size: " << ceil(static_cast<float>(size) / 1024 / 1024) << " Mbytes" << endl;
  cout << "Average node size: " << (size / nodes) << " bytes" << endl;

  auto frequency = sdd::tools::arcs<conf>(result);
  auto sequences = sdd::tools::sequences<conf>(result);

  // BUG here!
  size_t nb = 0;
  for (auto& p : sequences)
  {
//    cout << " == " << p.first << " => " << p.second << endl;
    nb += p.first * p.second;
  }
  cout << "!!!!! nb: " << nb << " =?= " << frequency[1].first << endl;

  size_t max_children = 0;
  for (auto& p : frequency)
  {
    max_children = max_children < p.first
                 ? p.first
                 : max_children;
  }
  size_t expected = 0;
  size_t bitfield_size = ceil(static_cast<float>(characters.size())/8);
  size_t base_size = bitfield_size + 4 + 8 + 1;
  cout << "Bit field size: " << bitfield_size << " bytes" << endl;
  cout << "Base node size: " << base_size << " bytes" << endl;
  const size_t average_length = 100;
  const size_t bitsize = ceil(log2(characters.size()));
  cout << "Bitsize: " << bitsize << endl;
  for (size_t i = 0; i <= max_children; ++i)
  {
    if (frequency[i].first == 0)
      continue;
    cout << left << setw(3) << i
         << " => "
         << left << setw(10) << frequency[i].first
         << right
         << endl;
    size_t subresult = 0;
    size_t subsize   = 0;
    if (i == 1)
    {
      size_t subcount = 0;
      for (const auto& p : sequences)
      {
        size_t size = base_size + 8 + ceil(static_cast<float>(bitsize)* p.first / 8);
        size += size % 8 == 0
              ? 0
              : 8 - (size % 8);

        size *= p.second;
        subresult += size;
        subsize   += p.second;
        subcount  += p.second * p.first;
        /*
        cout << "  For Length: " << p.first
             << endl
             << "    # Sequences: " << p.second
             << endl
             << "    String size: " << ceil((static_cast<float>(bitsize) * p.first) / 8)
             << " bytes"
             << endl
             << "    Size: " << size
             << " bytes"
             << endl
             << "    Average size: " << (size / p.second)
             << " bytes"
             << endl;
             */
      }
      subresult += (base_size + 8 + ceil(static_cast<float>(bitsize) / 8)) * (frequency[1].first - subcount);
      cout << "  Subcount: " << subcount << endl;
      cout << "  Frequency: " << frequency[i].first << endl;
      size_t average = 150;
      size_t should_size =
        (base_size + 8 + ceil(static_cast<float>(bitsize)*average / 8))
        * frequency[i].first / average;
      cout << "  Sould be: "
           << should_size
           << " bytes"
           << endl;
    }
    else
    {
      size_t size = base_size + i * 8;
      size += size % 8 == 0
            ? 0
            : 8 - (size % 8);
      subresult = size * frequency[i].first;
      subsize   = frequency[i].first;
    }
    cout << "  Total: " << subresult << " bytes"
         << endl
         << "  Average: " << (subresult / subsize) << " bytes"
         << endl;
    expected += subresult;
  }
  cout << "Expected size: " << ceil(static_cast<float>(expected) / 1024 / 1024) << " Mbytes" << endl;
  cout << "Original size: " << ceil(static_cast<float>(sum_inserted) / 1024 / 1024)
       << " Mbytes"
       << endl
       << "Binary size: " << (sum_inserted * bitsize / 8 / 1024 / 1024 + 1)
       << " Mbytes"
       << endl;

  if (nodes <= 5000)
  {
    ofstream of ("machin.dot");
    of << sdd::tools::dot (result, order);
  }

  return 0;
}
<commit_msg>Add min-length argument.<commit_after>#include <numeric>
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <set>
#include <csignal>
#include <cmath>
#include <ctgmath>

#include "sdd/sdd.hh"
#include "sdd/tools/size.hh"
#include "sdd/tools/nodes.hh"
#include "sdd/tools/arcs.hh"
#include "sdd/tools/sequences.hh"
#include "sdd/tools/dot/sdd.hh"

using namespace std;

static bool finish = false;

void
handler(int s)
{
  finish = true;
}

struct conf
  : public sdd::flat_set_default_configuration
{
  using Identifier = unsigned int;
  using Values     = sdd::values::flat_set<char>;
};
using SDD         = sdd::SDD<conf>;
using values_type = conf::Values;

int
main (int argc, const char** argv)
{
  const auto subsize = 100;
  if (argc == 0)
  {
    cerr << "sdd-stream <min-length> <max-length>" << endl;
    return 1;
  }

  struct sigaction sigIntHandler;
  sigIntHandler.sa_handler = handler;
  sigemptyset (&sigIntHandler.sa_mask);
  sigIntHandler.sa_flags = 0;
  sigaction (SIGINT, &sigIntHandler, NULL);

  size_t min_length = stoi (argv [1]);
  size_t max_length = stoi (argv [2]);

  vector<SDD> collections;
  collections.reserve (subsize);

  conf c;
  c.final_cleanup = false; // don't cleanup memory on manager scope exit.
  c.hom_cache_size = 2; // we don't use homomorphisms.
  c.hom_unique_table_size = 2; // we don't use homomorphisms.
//  c.sdd_intersection_cache_size = 16000000;
//  c.sdd_sum_cache_size = 16000000;
//  c.sdd_difference_cache_size = 16000000;
//  c.sdd_unique_table_size = 10000000;
  auto manager = sdd::init<conf>(c);

  // // Construct the SDD order: we need one level per letter.
  // vector<unsigned int> v (max_length);
  // iota (v.begin(), v.end(), 0);
  sdd::order_builder<conf> ob;
  const sdd::order<conf> order {sdd::order_builder<conf> ()};

  set<char> characters;

  size_t inserted = 0;
  size_t dropped  = 0;
  size_t total    = 0;
  size_t sum_inserted = 0;
  string line;
  line.reserve (80);
  string sequence;
  sequence.reserve (max_length);
  cout << "\033[s" << flush;
  while (getline (cin, line))
  {
    if (line [0] == '>')
    { // starting a new sequence:
      total += 1;
      if (sequence.size () != 0)
      {
        if ((sequence.size() >= min_length) && (sequence.size () <= max_length))
        {
          SDD word = SDD(0, SDD::eol::flat, sdd::one<conf>());
          for (auto i = 0u; i < sequence.size(); ++i)
          {
            characters.insert (sequence[sequence.size() - i - 1]);
            word = SDD(0, {sequence[sequence.size() - i - 1]}, word);
          }
          collections.emplace_back(word);
          inserted += 1;
          sum_inserted += sequence.size();
        }
        else
          dropped += 1;
        sequence.clear ();
      }
      if (finish)
        break;
    }
    else
      sequence += line;
    if (collections.size () == subsize)
    {
      const auto result = sdd::sum<conf> ( collections.cbegin()
                                         , collections.cend() );
      collections.clear ();
      collections.push_back (result);
    }
    if (total % 200 == 0)
      cout << "\033[u"
           << "inserted: " << inserted
           << " / "
           << "dropped: " << dropped
           << " / "
           << "total: " << total
           << flush;
  }
  if ((sequence.size() >= min_length) && (sequence.size () <= max_length))
  {
    SDD word = SDD(0, SDD::eol::flat, sdd::one<conf>());
    for (auto i = 0u; i < line.size(); ++i)
    {
      word = SDD(0, {line[line.size() - i - 1]}, word);
    }
    collections.emplace_back(word);
    inserted += 1;
    sum_inserted += sequence.size();
  }
  else
    dropped += 1;
  cout << "\033[u"
       << "inserted: " << inserted
       << " / "
       << "dropped: " << dropped
       << " / "
       << "total: " << total
       << endl;
  const auto result = sdd::sum<conf> ( collections.cbegin()
                                     , collections.cend() );

  cout << "# Characters: " << characters.size() << endl;
  cout << "# Words: " << result.size() << endl;
  const auto nodes = sdd::tools::nodes(result).first;
  cout << "# Nodes: " << nodes << endl;
  const auto size = sdd::tools::size(result);
  cout << "Size: " << ceil(static_cast<float>(size) / 1024 / 1024) << " Mbytes" << endl;
  cout << "Average node size: " << (size / nodes) << " bytes" << endl;

  auto frequency = sdd::tools::arcs<conf>(result);
  auto sequences = sdd::tools::sequences<conf>(result);

  // BUG here!
  size_t nb = 0;
  for (auto& p : sequences)
  {
//    cout << " == " << p.first << " => " << p.second << endl;
    nb += p.first * p.second;
  }
  cout << "!!!!! nb: " << nb << " =?= " << frequency[1].first << endl;

  size_t max_children = 0;
  for (auto& p : frequency)
  {
    max_children = max_children < p.first
                 ? p.first
                 : max_children;
  }
  size_t expected = 0;
  size_t bitfield_size = ceil(static_cast<float>(characters.size())/8);
  size_t base_size = bitfield_size + 4 + 8 + 1;
  cout << "Bit field size: " << bitfield_size << " bytes" << endl;
  cout << "Base node size: " << base_size << " bytes" << endl;
  const size_t average_length = 100;
  const size_t bitsize = ceil(log2(characters.size()));
  cout << "Bitsize: " << bitsize << endl;
  for (size_t i = 0; i <= max_children; ++i)
  {
    if (frequency[i].first == 0)
      continue;
    cout << left << setw(3) << i
         << " => "
         << left << setw(10) << frequency[i].first
         << right
         << endl;
    size_t subresult = 0;
    size_t subsize   = 0;
    if (i == 1)
    {
      size_t subcount = 0;
      for (const auto& p : sequences)
      {
        size_t size = base_size + 8 + ceil(static_cast<float>(bitsize)* p.first / 8);
        size += size % 8 == 0
              ? 0
              : 8 - (size % 8);

        size *= p.second;
        subresult += size;
        subsize   += p.second;
        subcount  += p.second * p.first;
        /*
        cout << "  For Length: " << p.first
             << endl
             << "    # Sequences: " << p.second
             << endl
             << "    String size: " << ceil((static_cast<float>(bitsize) * p.first) / 8)
             << " bytes"
             << endl
             << "    Size: " << size
             << " bytes"
             << endl
             << "    Average size: " << (size / p.second)
             << " bytes"
             << endl;
             */
      }
      subresult += (base_size + 8 + ceil(static_cast<float>(bitsize) / 8)) * (frequency[1].first - subcount);
      cout << "  Subcount: " << subcount << endl;
      cout << "  Frequency: " << frequency[i].first << endl;
      size_t average = 150;
      size_t should_size =
        (base_size + 8 + ceil(static_cast<float>(bitsize)*average / 8))
        * frequency[i].first / average;
      cout << "  Sould be: "
           << should_size
           << " bytes"
           << endl;
    }
    else
    {
      size_t size = base_size + i * 8;
      size += size % 8 == 0
            ? 0
            : 8 - (size % 8);
      subresult = size * frequency[i].first;
      subsize   = frequency[i].first;
    }
    cout << "  Total: " << subresult << " bytes"
         << endl
         << "  Average: " << (subresult / subsize) << " bytes"
         << endl;
    expected += subresult;
  }
  cout << "Expected size: " << ceil(static_cast<float>(expected) / 1024 / 1024) << " Mbytes" << endl;
  cout << "Original size: " << ceil(static_cast<float>(sum_inserted) / 1024 / 1024)
       << " Mbytes"
       << endl
       << "Binary size: " << (sum_inserted * bitsize / 8 / 1024 / 1024 + 1)
       << " Mbytes"
       << endl;

  if (nodes <= 5000)
  {
    ofstream of ("machin.dot");
    of << sdd::tools::dot (result, order);
  }

  return 0;
}
<|endoftext|>