<commit_before>#ifndef VSMC_UNIFORM_REAL_DISTRIBUTION_HPP
#define VSMC_UNIFORM_REAL_DISTRIBUTION_HPP

#include <vsmc/internal/common.hpp>
#include <vsmc/rng/u01.h>

#define VSMC_RUNTIME_ASSERT_RNG_UNIFORM_REAL_DISTRIBUTION_ENG_MIN(eng_min) \
    VSMC_RUNTIME_ASSERT((eng_min == 0),                                      \
            ("**vsmc::UniformRealDistribution::operator()** "                \
             "ENGINE MEMBER FUNCTION min() RETURN A VALUE OTHER THAN ZERO"))

#define VSMC_RUNTIME_ASSERT_RNG_UNIFORM_REAL_DISTRIBUTION_ENG_MAX \
    VSMC_RUNTIME_ASSERT(false,                                               \
            ("**vsmc::UniformRealDistribution::operator()** "                \
             "ENGINE MEMBER FUNCTION min() RETURN A VALUE OTHER THAN "       \
             "THE MAXIMUM OF uint32_t OR uint64_t"))

namespace vsmc {

namespace traits {

template<uint64_t, uint64_t> struct IntegerRangeTypeTrait;

template<>
struct IntegerRangeTypeTrait<0, ~((uint32_t)0)> {typedef uint32_t type;};

template<>
struct IntegerRangeTypeTrait<0, ~((uint64_t)0)> {typedef uint64_t type;};

} // namespace vsmc::traits

/// \brief Parameter type for open interval
/// \ingroup RNG
struct Open {};

/// \brief Parameter type for closed interval
/// \ingroup RNG
struct Closed {};

/// \brief Uniform real distribution with variants open/closed variants
/// \ingroup RNG
///
/// \details
/// This distribution is almost identical to C++11
/// `std::uniform_real_distribution`. But it differs in two important aspects
/// - It allows the interval to be either open or closed on both sides.
/// - It requires that the uniform random number generator to produce integers
///   on the full range of either `uint32_t` or `uint64_t`.
template <typename FPType, typename Left, typename Right>
class UniformRealDistribution
{
    private :

    typedef cxx11::integral_constant<std::size_t, sizeof(float)> f24;
    typedef cxx11::integral_constant<std::size_t, sizeof(double)> f53;
    typedef cxx11::integral_constant<std::size_t, sizeof(uint32_t)> u32;
    typedef cxx11::integral_constant<std::size_t, sizeof(uint64_t)> u64;

    public :

    typedef FPType result_type;

    class param_type
    {
        public :

        typedef FPType result_type;

        typedef UniformRealDistribution<FPType, Left, Right>
            distribution_type;

        explicit param_type (result_type a = 0, result_type b = 1) :
            a_(a), b_(b) {}

        result_type a () const {return a_;}
        result_type b () const {return b_;}

        friend inline bool operator== (
                const param_type &param1, const param_type &param2)
        {return (param1.a() == param2.a()) && (param1.b() == param2.b());}

        friend inline bool operator!= (
                const param_type param1, const param_type param2)
        {return (param1.a() != param2.a()) || (param1.b() != param2.b());}

        template <typename CharT, typename Traits>
        friend inline std::basic_ostream<CharT, Traits> &operator<< (
                std::basic_ostream<CharT, Traits> &os, const param_type &param)
        {
            os << param.a() << ' ' << param.b();

            return os;
        }

        template <typename CharT, typename Traits>
        friend inline std::basic_istream<CharT, Traits> &operator>> (
                std::basic_istream<CharT, Traits> &is, param_type &param)
        {
            result_type a;
            result_type b;
            if (is >> a >> std::ws >> b) {
                if (a <= b)
                    param = param_type(param_type(a, b));
                else
                    is.setstate(std::ios_base::failbit);
            }

            return is;
        }

        private :

        result_type a_;
        result_type b_;
    }; // class param_type

    explicit UniformRealDistribution (result_type a = 0, result_type b = 1) :
        a_(a), b_(b) {}

    UniformRealDistribution (const param_type &param) :
        a_(param.a()), b_(param.b()) {}

    param_type param () const {return param_type(a_, b_);}

    void param (const param_type &param)
    {
        a_ = param.a();
        b_ = param.b();
    }

    void reset () const {}

    result_type a () const {return a_;}
    result_type b () const {return b_;}
    result_type min VSMC_MACRO_NO_EXPANSION () const {return a_;}
    result_type max VSMC_MACRO_NO_EXPANSION () const {return b_;}

    template <typename Eng>
    result_type operator() (Eng &eng) const
    {
        typedef cxx11::integral_constant<std::size_t, sizeof(result_type)>
            fp_bits;

#if VSMC_HAS_CXX11LIB_RANDOM_CONSTEXPR_MINMAX
        typedef typename traits::IntegerRangeTypeTrait<
            Eng::min VSMC_MACRO_NO_EXPANSION (),
            Eng::max VSMC_MACRO_NO_EXPANSION ()>::type eng_uint_t;
        typedef cxx11::integral_constant<std::size_t, sizeof(eng_uint_t)>
            u_bits;

        result_type u = u01(static_cast<eng_uint_t>(eng()), Left(), Right(),
                u_bits(), fp_bits());
#else // VSMC_HAS_CXX11LIB_RANDOM_CONSTEXPR_MINMAX
        static VSMC_CONSTEXPR const uint64_t eng_min = static_cast<uint64_t>(
                eng.min VSMC_MACRO_NO_EXPANSION ());
        VSMC_RUNTIME_ASSERT_RNG_UNIFORM_REAL_DISTRIBUTION_ENG_MIN(eng_min);

        result_type u = 0;
        static VSMC_CONSTEXPR const uint64_t eng_max = static_cast<uint64_t>(
                eng.max VSMC_MACRO_NO_EXPANSION ());
        switch (eng_max) {
            case uint32_t_max_ :
                u = u01(static_cast<uint32_t>(eng()), Left(), Right(),
                        u32(), fp_bits());
                break;
            case uint64_t_max_ :
                u = u01(static_cast<uint64_t>(eng()), Left(), Right(),
                        u64(), fp_bits());
                break;
            default :
                VSMC_RUNTIME_ASSERT_RNG_UNIFORM_REAL_DISTRIBUTION_ENG_MAX;
        }
#endif // VSMC_HAS_CXX11LIB_RANDOM_CONSTEXPR_MINMAX

        return u * (b_ - a_) + a_;
    }

    private :

    result_type a_;
    result_type b_;

#if !VSMC_HAS_CXX11LIB_RANDOM_CONSTEXPR_MINMAX
    static VSMC_CONSTEXPR const uint64_t uint32_t_max_ = ~((uint32_t)0);
    static VSMC_CONSTEXPR const uint64_t uint64_t_max_ = ~((uint64_t)0);
#endif

    static float u01(uint32_t i, Open, Open, u32, f24)
    {return ::u01_open_open_32_24(i);}

    static float u01(uint32_t i, Open, Closed, u32, f24)
    {return ::u01_open_closed_32_24(i);}

    static float u01(uint32_t i, Closed, Open, u32, f24)
    {return ::u01_closed_open_32_24(i);}

    static float u01(uint32_t i, Closed, Closed, u32, f24)
    {return ::u01_closed_closed_32_24(i);}

    static double u01(uint32_t i, Open, Open, u32, f53)
    {return ::u01_open_open_32_53(i);}

    static double u01(uint32_t i, Open, Closed, u32, f53)
    {return ::u01_open_closed_32_53(i);}

    static double u01(uint32_t i, Closed, Open, u32, f53)
    {return ::u01_closed_open_32_53(i);}

    static double u01(uint32_t i, Closed, Closed, u32, f53)
    {return ::u01_closed_closed_32_53(i);}

    static float u01(uint64_t i, Open, Open, u64, f24)
    {return static_cast<float>(::u01_open_open_64_53(i));}

    static float u01(uint64_t i, Open, Closed, u64, f24)
    {return static_cast<float>(::u01_open_closed_64_53(i));}

    static float u01(uint64_t i, Closed, Open, u64, f24)
    {return static_cast<float>(::u01_closed_open_64_53(i));}

    static float u01(uint64_t i, Closed, Closed, u64, f24)
    {return static_cast<float>(::u01_closed_closed_64_53(i));}

    static double u01(uint64_t i, Open, Open, u64, f53)
    {return ::u01_open_open_64_53(i);}

    static double u01(uint64_t i, Open, Closed, u64, f53)
    {return ::u01_open_closed_64_53(i);}

    static double u01(uint64_t i, Closed, Open, u64, f53)
    {return ::u01_closed_open_64_53(i);}

    static double u01(uint64_t i, Closed, Closed, u64, f53)
    {return ::u01_closed_closed_64_53(i);}
}; // class UniformRealDistributionBase

/// \brief UniformRealDistribution operator==
/// \ingroup RNG
template <typename FPType, typename Left, typename Right>
inline bool operator== (
        const UniformRealDistribution<FPType, Left, Right> &runif1,
        const UniformRealDistribution<FPType, Left, Right> &runif2)
{
    return (runif1.a() == runif2.a()) && (runif1.b() == runif2.b());
}

/// \brief UniformRealDistribution operator!=
/// \ingroup RNG
template <typename FPType, typename Left, typename Right>
inline bool operator!= (
        const UniformRealDistribution<FPType, Left, Right> &runif1,
        const UniformRealDistribution<FPType, Left, Right> &runif2)
{
    return (runif1.a() != runif2.a()) || (runif1.b() != runif2.b());
}

/// \brief UniformRealDistribution operator<<
/// \ingroup RNG
template <typename CharT, typename Traits,
         typename FPType, typename Left, typename Right>
inline std::basic_ostream<CharT, Traits> &operator<< (
        std::basic_ostream<CharT, Traits> &os,
        const UniformRealDistribution<FPType, Left, Right> &runif)
{
    os << runif.a() << ' ' << runif.b();

    return os;
}

/// \brief UniformRealDistribution operator>>
/// \ingroup RNG
template <typename CharT, typename Traits,
         typename FPType, typename Left, typename Right>
inline std::basic_istream<CharT, Traits> &operator>> (
        std::basic_istream<CharT, Traits> &is,
        UniformRealDistribution<FPType, Left, Right> &runif)
{
    typedef typename UniformRealDistribution<FPType, Left, Right>::param_type
        param_type;

    FPType a;
    FPType b;
    if (is >> a >> std::ws >> b) {
        if (a <= b)
            runif.param(param_type(a, b));
        else
            is.setstate(std::ios_base::failbit);
    }

    return is;
}

} // namespace vsmc

#endif // VSMC_UNIFORM_REAL_DISTRIBUTION_HPP
<commit_msg>suppress garbage value warning<commit_after>#ifndef VSMC_UNIFORM_REAL_DISTRIBUTION_HPP
#define VSMC_UNIFORM_REAL_DISTRIBUTION_HPP

#include <vsmc/internal/common.hpp>
#include <vsmc/rng/u01.h>

#define VSMC_RUNTIME_ASSERT_RNG_UNIFORM_REAL_DISTRIBUTION_ENG_MIN(eng_min) \
    VSMC_RUNTIME_ASSERT((eng_min == 0),                                      \
            ("**vsmc::UniformRealDistribution::operator()** "                \
             "ENGINE MEMBER FUNCTION min() RETURN A VALUE OTHER THAN ZERO"))

#define VSMC_RUNTIME_ASSERT_RNG_UNIFORM_REAL_DISTRIBUTION_ENG_MAX \
    VSMC_RUNTIME_ASSERT(false,                                               \
            ("**vsmc::UniformRealDistribution::operator()** "                \
             "ENGINE MEMBER FUNCTION min() RETURN A VALUE OTHER THAN "       \
             "THE MAXIMUM OF uint32_t OR uint64_t"))

namespace vsmc {

namespace traits {

template<uint64_t, uint64_t> struct IntegerRangeTypeTrait;

template<>
struct IntegerRangeTypeTrait<0, ~((uint32_t)0)> {typedef uint32_t type;};

template<>
struct IntegerRangeTypeTrait<0, ~((uint64_t)0)> {typedef uint64_t type;};

} // namespace vsmc::traits

/// \brief Parameter type for open interval
/// \ingroup RNG
struct Open {};

/// \brief Parameter type for closed interval
/// \ingroup RNG
struct Closed {};

/// \brief Uniform real distribution with variants open/closed variants
/// \ingroup RNG
///
/// \details
/// This distribution is almost identical to C++11
/// `std::uniform_real_distribution`. But it differs in two important aspects
/// - It allows the interval to be either open or closed on both sides.
/// - It requires that the uniform random number generator to produce integers
///   on the full range of either `uint32_t` or `uint64_t`.
template <typename FPType, typename Left, typename Right>
class UniformRealDistribution
{
    private :

    typedef cxx11::integral_constant<std::size_t, sizeof(float)> f24;
    typedef cxx11::integral_constant<std::size_t, sizeof(double)> f53;
    typedef cxx11::integral_constant<std::size_t, sizeof(uint32_t)> u32;
    typedef cxx11::integral_constant<std::size_t, sizeof(uint64_t)> u64;

    public :

    typedef FPType result_type;

    class param_type
    {
        public :

        typedef FPType result_type;

        typedef UniformRealDistribution<FPType, Left, Right>
            distribution_type;

        explicit param_type (result_type a = 0, result_type b = 1) :
            a_(a), b_(b) {}

        result_type a () const {return a_;}
        result_type b () const {return b_;}

        friend inline bool operator== (
                const param_type &param1, const param_type &param2)
        {return (param1.a() == param2.a()) && (param1.b() == param2.b());}

        friend inline bool operator!= (
                const param_type param1, const param_type param2)
        {return (param1.a() != param2.a()) || (param1.b() != param2.b());}

        template <typename CharT, typename Traits>
        friend inline std::basic_ostream<CharT, Traits> &operator<< (
                std::basic_ostream<CharT, Traits> &os, const param_type &param)
        {
            os << param.a() << ' ' << param.b();

            return os;
        }

        template <typename CharT, typename Traits>
        friend inline std::basic_istream<CharT, Traits> &operator>> (
                std::basic_istream<CharT, Traits> &is, param_type &param)
        {
            result_type a;
            result_type b;
            if (is >> a >> std::ws >> b) {
                if (a <= b)
                    param = param_type(param_type(a, b));
                else
                    is.setstate(std::ios_base::failbit);
            }

            return is;
        }

        private :

        result_type a_;
        result_type b_;
    }; // class param_type

    explicit UniformRealDistribution (result_type a = 0, result_type b = 1) :
        a_(a), b_(b) {}

    UniformRealDistribution (const param_type &param) :
        a_(param.a()), b_(param.b()) {}

    param_type param () const {return param_type(a_, b_);}

    void param (const param_type &param)
    {
        a_ = param.a();
        b_ = param.b();
    }

    void reset () const {}

    result_type a () const {return a_;}
    result_type b () const {return b_;}
    result_type min VSMC_MACRO_NO_EXPANSION () const {return a_;}
    result_type max VSMC_MACRO_NO_EXPANSION () const {return b_;}

    template <typename Eng>
    result_type operator() (Eng &eng) const
    {
        typedef cxx11::integral_constant<std::size_t, sizeof(result_type)>
            fp_bits;

#if VSMC_HAS_CXX11LIB_RANDOM_CONSTEXPR_MINMAX
        typedef typename traits::IntegerRangeTypeTrait<
            Eng::min VSMC_MACRO_NO_EXPANSION (),
            Eng::max VSMC_MACRO_NO_EXPANSION ()>::type eng_uint_t;
        typedef cxx11::integral_constant<std::size_t, sizeof(eng_uint_t)>
            u_bits;

        result_type u = u01(static_cast<eng_uint_t>(eng()), Left(), Right(),
                u_bits(), fp_bits());
#else // VSMC_HAS_CXX11LIB_RANDOM_CONSTEXPR_MINMAX
        static VSMC_CONSTEXPR const uint64_t eng_min = static_cast<uint64_t>(
                eng.min VSMC_MACRO_NO_EXPANSION ());
        VSMC_RUNTIME_ASSERT_RNG_UNIFORM_REAL_DISTRIBUTION_ENG_MIN(eng_min);

        result_type u = 0;
        static VSMC_CONSTEXPR const uint64_t eng_max = static_cast<uint64_t>(
                eng.max VSMC_MACRO_NO_EXPANSION ());
        switch (eng_max) {
            case uint32_t_max_ :
                u = u01(static_cast<uint32_t>(eng()), Left(), Right(),
                        u32(), fp_bits());
                break;
            case uint64_t_max_ :
                u = u01(static_cast<uint64_t>(eng()), Left(), Right(),
                        u64(), fp_bits());
                break;
            default :
                VSMC_RUNTIME_ASSERT_RNG_UNIFORM_REAL_DISTRIBUTION_ENG_MAX;
        }
#endif // VSMC_HAS_CXX11LIB_RANDOM_CONSTEXPR_MINMAX

        return u * (b_ - a_) + a_;
    }

    private :

    result_type a_;
    result_type b_;

#if !VSMC_HAS_CXX11LIB_RANDOM_CONSTEXPR_MINMAX
    static VSMC_CONSTEXPR const uint64_t uint32_t_max_ = ~((uint32_t)0);
    static VSMC_CONSTEXPR const uint64_t uint64_t_max_ = ~((uint64_t)0);
#endif

    static float u01(uint32_t i, Open, Open, u32, f24)
    {return ::u01_open_open_32_24(i);}

    static float u01(uint32_t i, Open, Closed, u32, f24)
    {return ::u01_open_closed_32_24(i);}

    static float u01(uint32_t i, Closed, Open, u32, f24)
    {return ::u01_closed_open_32_24(i);}

    static float u01(uint32_t i, Closed, Closed, u32, f24)
    {return ::u01_closed_closed_32_24(i);}

    static double u01(uint32_t i, Open, Open, u32, f53)
    {return ::u01_open_open_32_53(i);}

    static double u01(uint32_t i, Open, Closed, u32, f53)
    {return ::u01_open_closed_32_53(i);}

    static double u01(uint32_t i, Closed, Open, u32, f53)
    {return ::u01_closed_open_32_53(i);}

    static double u01(uint32_t i, Closed, Closed, u32, f53)
    {return ::u01_closed_closed_32_53(i);}

    static float u01(uint64_t i, Open, Open, u64, f24)
    {return static_cast<float>(::u01_open_open_64_53(i));}

    static float u01(uint64_t i, Open, Closed, u64, f24)
    {return static_cast<float>(::u01_open_closed_64_53(i));}

    static float u01(uint64_t i, Closed, Open, u64, f24)
    {return static_cast<float>(::u01_closed_open_64_53(i));}

    static float u01(uint64_t i, Closed, Closed, u64, f24)
    {return static_cast<float>(::u01_closed_closed_64_53(i));}

    static double u01(uint64_t i, Open, Open, u64, f53)
    {return ::u01_open_open_64_53(i);}

    static double u01(uint64_t i, Open, Closed, u64, f53)
    {return ::u01_open_closed_64_53(i);}

    static double u01(uint64_t i, Closed, Open, u64, f53)
    {return ::u01_closed_open_64_53(i);}

    static double u01(uint64_t i, Closed, Closed, u64, f53)
    {return ::u01_closed_closed_64_53(i);}
}; // class UniformRealDistributionBase

/// \brief UniformRealDistribution operator==
/// \ingroup RNG
template <typename FPType, typename Left, typename Right>
inline bool operator== (
        const UniformRealDistribution<FPType, Left, Right> &runif1,
        const UniformRealDistribution<FPType, Left, Right> &runif2)
{
    return (runif1.a() == runif2.a()) && (runif1.b() == runif2.b());
}

/// \brief UniformRealDistribution operator!=
/// \ingroup RNG
template <typename FPType, typename Left, typename Right>
inline bool operator!= (
        const UniformRealDistribution<FPType, Left, Right> &runif1,
        const UniformRealDistribution<FPType, Left, Right> &runif2)
{
    return (runif1.a() != runif2.a()) || (runif1.b() != runif2.b());
}

/// \brief UniformRealDistribution operator<<
/// \ingroup RNG
template <typename CharT, typename Traits,
         typename FPType, typename Left, typename Right>
inline std::basic_ostream<CharT, Traits> &operator<< (
        std::basic_ostream<CharT, Traits> &os,
        const UniformRealDistribution<FPType, Left, Right> &runif)
{
    os << runif.a() << ' ' << runif.b();

    return os;
}

/// \brief UniformRealDistribution operator>>
/// \ingroup RNG
template <typename CharT, typename Traits,
         typename FPType, typename Left, typename Right>
inline std::basic_istream<CharT, Traits> &operator>> (
        std::basic_istream<CharT, Traits> &is,
        UniformRealDistribution<FPType, Left, Right> &runif)
{
    typedef typename UniformRealDistribution<FPType, Left, Right>::param_type
        param_type;

    FPType a = 0;
    FPType b = 0;
    if (is >> a >> std::ws >> b) {
        if (a <= b)
            runif.param(param_type(a, b));
        else
            is.setstate(std::ios_base::failbit);
    }

    return is;
}

} // namespace vsmc

#endif // VSMC_UNIFORM_REAL_DISTRIBUTION_HPP
<|endoftext|>


<commit_before>#include <fstream>
#include <string>
#include <string.h>
#include <iostream>

#include "io.hh"
#include "str.hh"
#include "conf.hh"
#include "HmmSet.hh"
#include "FeatureGenerator.hh"
#include "Recipe.hh"

std::string out_file;
std::string save_summary_file;

int info;
int accum_pos;
bool raw_flag;
bool transtat;
bool durstat;
float start_time, end_time;
int start_frame, end_frame;

conf::Config config;
Recipe recipe;
HmmSet model;
FeatureGenerator fea_gen;

void
train(HmmSet *model, Segmentator *segmentator)
{
  int frame;

  while (segmentator->next_frame()) {

    // Fetch the current feature vector
    frame = segmentator->current_frame();
    FeatureVec feature = fea_gen.generate(frame);
    model->reset_cache();

    // Accumulate all possible states distributions for this frame
    const std::vector<Segmentator::IndexProbPair> &pdfs
      = segmentator->pdf_probs();
    for (int i = 0; i < (int)pdfs.size(); i++)
      model->accumulate_distribution(feature, pdfs[i].index,
                                     pdfs[i].prob, accum_pos);

    // Accumulate also transition probabilities if desired
    if (transtat) {

      const std::vector<Segmentator::IndexProbPair> &transitions
        = segmentator->transition_probs();

      for (int i = 0; i < (int)transitions.size(); i++)
        model->accumulate_transition(transitions[i].index,
                                     transitions[i].prob);
    }
  }
}

int
main(int argc, char *argv[])
{
  Segmentator *segmentator;
  try {
    config("usage: stats [OPTION...]\n")
      ('h', "help", "", "", "display help")
      ('b', "base=BASENAME", "arg", "", "base filename for model files")
      ('g', "gk=FILE", "arg", "", "Mixture base distributions")
      ('m', "mc=FILE", "arg", "", "Mixture coefficients for the states")
      ('p', "ph=FILE", "arg", "", "HMM definitions")
      ('c', "config=FILE", "arg must", "", "feature configuration")
      ('r', "recipe=FILE", "arg must", "", "recipe file")
      ('O', "ophn", "", "", "use output phns for training")
      ('H', "hmmnet", "", "", "use HMM networks for training")
      ('D', "den-hmmnet", "", "", "use denominator HMM networks for training")
      ('o', "out=BASENAME", "arg must", "", "base filename for output statistics")
      ('R', "raw-input", "", "", "raw audio input")
      ('t', "transitions", "", "", "collect also state transition statistics")
      ('d', "durstat", "", "", "collect also duration statistics")
      ('F', "fw-beam=FLOAT", "arg", "0", "Forward beam (for lattice-based training)")
      ('W', "bw-beam=FLOAT", "arg", "0", "Backward beam (for lattice-based training)")
      ('A', "ac-scale=FLOAT", "arg", "1", "Acoustic scaling (for lattice-based training)")
      ('s', "savesum=FILE", "arg", "", "save summary information (loglikelihood etc.)")
      ('S', "speakers=FILE", "arg", "", "speaker configuration file")
      ('B', "batch=INT", "arg", "0", "number of batch processes with the same recipe")
      ('I', "bindex=INT", "arg", "0", "batch process index")
      ('i', "info=INT", "arg", "0", "info level")
      ;
    config.default_parse(argc, argv);

    info = config["info"].get_int();
    raw_flag = config["raw-input"].specified;
    fea_gen.load_configuration(io::Stream(config["config"].get_str()));

    // Initialize the model for accumulating ML statistics
    if (config["base"].specified)
    {
      model.read_all(config["base"].get_str());
    }
    else if (config["gk"].specified && config["mc"].specified &&
             config["ph"].specified)
    {
      model.read_gk(config["gk"].get_str());
      model.read_mc(config["mc"].get_str());
      model.read_ph(config["ph"].get_str());
    }
    else
    {
      throw std::string("Must give either --base or all --gk, --mc and --ph");
    }
    out_file = config["out"].get_str();

    if (config["savesum"].specified)
      save_summary_file = config["savesum"].get_str();

    if (config["batch"].specified^config["bindex"].specified)
      throw std::string("Must give both --batch and --bindex");

    // Check for state transition statistics
    transtat = config["transitions"].specified;
    if (transtat)
      fprintf(stderr, "You have defined --transitions option: state transition statistics will be collected as well\n");

    // Check for duration statistics
    durstat = config["durstat"].specified;
    if (durstat)
      fprintf(stderr, "You have defined --durstat option: duration statistics will be collected as well\n");

    // Check the dimension
    if (model.dim() != fea_gen.dim()) {
      throw str::fmt(128,
		     "gaussian dimension is %d but feature dimension is %d",
                     model.dim(), fea_gen.dim());
    }

    // Read recipe file
    recipe.read(io::Stream(config["recipe"].get_str()),
                config["batch"].get_int(), config["bindex"].get_int(),
                true);

    // Configure the model for accumulating
    if (config["den-hmmnet"].specified) {
      model.set_estimation_mode(PDF::MMI);
      accum_pos=1;
    }
    else {
      model.set_estimation_mode(PDF::ML);
      accum_pos=0;
    }
    model.start_accumulating();

    // Process each recipe line
    for (int f = 0; f < (int)recipe.infos.size(); f++)
    {

      // Print file name, start and end times to stderr
      if (info > 0)
      {
        fprintf(stderr, "Processing file: %s",
                recipe.infos[f].audio_path.c_str());
        if (recipe.infos[f].start_time || recipe.infos[f].end_time)
          fprintf(stderr," (%.2f-%.2f)",recipe.infos[f].start_time,
                  recipe.infos[f].end_time);
        fprintf(stderr,"\n");
      }

      if (config["hmmnet"].specified || config["den-hmmnet"].specified)
      {
        // Open files and configure
        HmmNetBaumWelch* lattice =
          recipe.infos[f].init_hmmnet_files(&model,
                                            config["den-hmmnet"].specified,
                                            &fea_gen, raw_flag, NULL);
        lattice->set_collect_transition_probs(transtat);
        lattice->set_pruning_thresholds(config["bw-beam"].get_float(), config["fw-beam"].get_float());
        if (config["ac-scale"].specified)
          lattice->set_acoustic_scaling(config["ac-scale"].get_float());

        double orig_beam = lattice->get_backward_beam();
        int counter = 1;
        while (!lattice->init_utterance_segmentation())
        {
          if (counter >= 5)
          {
            throw std::string("Could not run Baum-Welch.\n") +
              std::string("The HMM network may be incorrect or initial beam too low.");
          }
          fprintf(stderr,
                  "Warning: Backward phase failed, increasing beam to %.1f\n",
                  ++counter*orig_beam);
          lattice->set_pruning_thresholds(counter*orig_beam, 0);
        }
        segmentator = lattice;
      }
      else
      {
        PhnReader* phnreader =
          recipe.infos[f].init_phn_files(&model, false, false,
                                         config["ophn"].specified, &fea_gen,
                                         config["raw-input"].specified, NULL);
        phnreader->set_collect_transition_probs(transtat);
        segmentator = phnreader;
        if (!segmentator->init_utterance_segmentation())
          throw std::string("Could not initialize the utterance for PhnReader");
      }

      // Train
      train(&model, segmentator);

      // Clean up
      delete segmentator;
      fea_gen.close();
    }

    if (info > 0)
    {
      fprintf(stderr, "Finished collecting statistics (%i/%i), writing models\n",
	      config["batch"].get_int(), config["bindex"].get_int());
    }

    // Write statistics to file dump and clean up
    model.dump_statistics(out_file);
    model.stop_accumulating();
  }

  // Handle errors
  catch (HmmSet::UnknownHmm &e) {
    fprintf(stderr,
	    "Unknown HMM in transcription, "
	    "writing incompletely taught models\n");
    abort();
  }

  catch (std::exception &e) {
    fprintf(stderr, "exception: %s\n", e.what());
    abort();
  }

  catch (std::string &str) {
    fprintf(stderr, "exception: %s\n", str.c_str());
    abort();
  }
}
<commit_msg>total log likelihood printti<commit_after>#include <fstream>
#include <string>
#include <string.h>
#include <iostream>

#include "io.hh"
#include "str.hh"
#include "conf.hh"
#include "HmmSet.hh"
#include "FeatureGenerator.hh"
#include "Recipe.hh"
#include "util.hh"

std::string out_file;
std::string save_summary_file;

int info;
int accum_pos;
bool raw_flag;
bool transtat;
bool durstat;
float start_time, end_time;
int start_frame, end_frame;
double total_log_likelihood=0;

conf::Config config;
Recipe recipe;
HmmSet model;
FeatureGenerator fea_gen;

void
train(HmmSet *model, Segmentator *segmentator)
{
  int frame;

  while (segmentator->next_frame()) {

    // Fetch the current feature vector
    frame = segmentator->current_frame();
    FeatureVec feature = fea_gen.generate(frame);
    model->reset_cache();

    // Accumulate all possible states distributions for this frame
    const std::vector<Segmentator::IndexProbPair> &pdfs
      = segmentator->pdf_probs();
    for (int i = 0; i < (int)pdfs.size(); i++) {
      model->accumulate_distribution(feature, pdfs[i].index,
                                     pdfs[i].prob, accum_pos);
      total_log_likelihood += util::safe_log(pdfs[i].prob);
    }

    // Accumulate also transition probabilities if desired
    if (transtat) {

      const std::vector<Segmentator::IndexProbPair> &transitions
        = segmentator->transition_probs();

      for (int i = 0; i < (int)transitions.size(); i++) {
        model->accumulate_transition(transitions[i].index,
                                     transitions[i].prob);
        total_log_likelihood += util::safe_log(transitions[i].prob);
      }
    }
  }
}

int
main(int argc, char *argv[])
{
  Segmentator *segmentator;
  try {
    config("usage: stats [OPTION...]\n")
      ('h', "help", "", "", "display help")
      ('b', "base=BASENAME", "arg", "", "base filename for model files")
      ('g', "gk=FILE", "arg", "", "Mixture base distributions")
      ('m', "mc=FILE", "arg", "", "Mixture coefficients for the states")
      ('p', "ph=FILE", "arg", "", "HMM definitions")
      ('c', "config=FILE", "arg must", "", "feature configuration")
      ('r', "recipe=FILE", "arg must", "", "recipe file")
      ('O', "ophn", "", "", "use output phns for training")
      ('H', "hmmnet", "", "", "use HMM networks for training")
      ('D', "den-hmmnet", "", "", "use denominator HMM networks for training")
      ('o', "out=BASENAME", "arg must", "", "base filename for output statistics")
      ('R', "raw-input", "", "", "raw audio input")
      ('t', "transitions", "", "", "collect also state transition statistics")
      ('d', "durstat", "", "", "collect also duration statistics")
      ('F', "fw-beam=FLOAT", "arg", "0", "Forward beam (for lattice-based training)")
      ('W', "bw-beam=FLOAT", "arg", "0", "Backward beam (for lattice-based training)")
      ('A', "ac-scale=FLOAT", "arg", "1", "Acoustic scaling (for lattice-based training)")
      ('s', "savesum=FILE", "arg", "", "save summary information (loglikelihood etc.)")
      ('S', "speakers=FILE", "arg", "", "speaker configuration file")
      ('B', "batch=INT", "arg", "0", "number of batch processes with the same recipe")
      ('I', "bindex=INT", "arg", "0", "batch process index")
      ('i', "info=INT", "arg", "0", "info level")
      ;
    config.default_parse(argc, argv);

    info = config["info"].get_int();
    raw_flag = config["raw-input"].specified;
    fea_gen.load_configuration(io::Stream(config["config"].get_str()));

    // Initialize the model for accumulating ML statistics
    if (config["base"].specified)
    {
      model.read_all(config["base"].get_str());
    }
    else if (config["gk"].specified && config["mc"].specified &&
             config["ph"].specified)
    {
      model.read_gk(config["gk"].get_str());
      model.read_mc(config["mc"].get_str());
      model.read_ph(config["ph"].get_str());
    }
    else
    {
      throw std::string("Must give either --base or all --gk, --mc and --ph");
    }
    out_file = config["out"].get_str();

    if (config["savesum"].specified)
      save_summary_file = config["savesum"].get_str();

    if (config["batch"].specified^config["bindex"].specified)
      throw std::string("Must give both --batch and --bindex");

    // Check for state transition statistics
    transtat = config["transitions"].specified;
    if (transtat)
      fprintf(stderr, "You have defined --transitions option: state transition statistics will be collected as well\n");

    // Check for duration statistics
    durstat = config["durstat"].specified;
    if (durstat)
      fprintf(stderr, "You have defined --durstat option: duration statistics will be collected as well\n");

    // Check the dimension
    if (model.dim() != fea_gen.dim()) {
      throw str::fmt(128,
		     "gaussian dimension is %d but feature dimension is %d",
                     model.dim(), fea_gen.dim());
    }

    // Read recipe file
    recipe.read(io::Stream(config["recipe"].get_str()),
                config["batch"].get_int(), config["bindex"].get_int(),
                true);

    // Configure the model for accumulating
    if (config["den-hmmnet"].specified) {
      model.set_estimation_mode(PDF::MMI);
      accum_pos=1;
    }
    else {
      model.set_estimation_mode(PDF::ML);
      accum_pos=0;
    }
    model.start_accumulating();

    // Process each recipe line
    for (int f = 0; f < (int)recipe.infos.size(); f++)
    {

      // Print file name, start and end times to stderr
      if (info > 0)
      {
        fprintf(stderr, "Processing file: %s",
                recipe.infos[f].audio_path.c_str());
        if (recipe.infos[f].start_time || recipe.infos[f].end_time)
          fprintf(stderr," (%.2f-%.2f)",recipe.infos[f].start_time,
                  recipe.infos[f].end_time);
        fprintf(stderr,"\n");
      }

      if (config["hmmnet"].specified || config["den-hmmnet"].specified)
      {
        // Open files and configure
        HmmNetBaumWelch* lattice =
          recipe.infos[f].init_hmmnet_files(&model,
                                            config["den-hmmnet"].specified,
                                            &fea_gen, raw_flag, NULL);
        lattice->set_collect_transition_probs(transtat);
        lattice->set_pruning_thresholds(config["bw-beam"].get_float(), config["fw-beam"].get_float());
        if (config["ac-scale"].specified)
          lattice->set_acoustic_scaling(config["ac-scale"].get_float());

        double orig_beam = lattice->get_backward_beam();
        int counter = 1;
        while (!lattice->init_utterance_segmentation())
        {
          if (counter >= 5)
          {
            throw std::string("Could not run Baum-Welch.\n") +
              std::string("The HMM network may be incorrect or initial beam too low.");
          }
          fprintf(stderr,
                  "Warning: Backward phase failed, increasing beam to %.1f\n",
                  ++counter*orig_beam);
          lattice->set_pruning_thresholds(counter*orig_beam, 0);
        }
        segmentator = lattice;
      }
      else
      {
        PhnReader* phnreader =
          recipe.infos[f].init_phn_files(&model, false, false,
                                         config["ophn"].specified, &fea_gen,
                                         config["raw-input"].specified, NULL);
        phnreader->set_collect_transition_probs(transtat);
        segmentator = phnreader;
        if (!segmentator->init_utterance_segmentation())
          throw std::string("Could not initialize the utterance for PhnReader");
      }

      // Train
      train(&model, segmentator);

      // Clean up
      delete segmentator;
      fea_gen.close();
    }

    if (info > 0)
    {
      fprintf(stderr, "Finished collecting statistics (%i/%i), writing models\n",
	      config["batch"].get_int(), config["bindex"].get_int());
      fprintf(stderr, "Total log likelihood: %f\n", total_log_likelihood);
    }

    // Write statistics to file dump and clean up
    model.dump_statistics(out_file);
    model.stop_accumulating();
  }

  // Handle errors
  catch (HmmSet::UnknownHmm &e) {
    fprintf(stderr,
	    "Unknown HMM in transcription, "
	    "writing incompletely taught models\n");
    abort();
  }

  catch (std::exception &e) {
    fprintf(stderr, "exception: %s\n", e.what());
    abort();
  }

  catch (std::string &str) {
    fprintf(stderr, "exception: %s\n", str.c_str());
    abort();
  }
}
<|endoftext|>


<commit_before>// Copyright (c) 2014 Jae-jun Kang
// See the file COPYING for license details.

#ifndef X2BOOST_SINGLE_THREADED_FLOW_HPP_
#define X2BOOST_SINGLE_THREADED_FLOW_HPP_

#ifndef X2BOOST_PRE_HPP_
#include "x2boost/pre.hpp"
#endif

#include <boost/bind.hpp>
#include <boost/thread.hpp>

#include "x2boost/flows/event_based_flow.hpp"

namespace x2
{
    template<class Q = synchronized_event_queue>
    class X2BOOST_API single_threaded_flow : public event_based_flow<Q>
    {
    public:
        single_threaded_flow() : thread_(NULL) {}

        virtual ~single_threaded_flow() {}

        virtual void startup()
        {
            boost::mutex::scoped_lock lock(flow::mutex_);
            if (thread_) { return; }

            this->setup();
            flow::case_stack_.setup(shared_from_this());

            thread_ = new boost::thread(boost::bind(&event_based_flow<Q>::run, this));
        }

        virtual void shutdown()
        {
            boost::mutex::scoped_lock lock(flow::mutex_);
            if (!thread_) { return; }

            // enqueue flow_stop
            queue_.close();

            thread_->join();
            delete thread_;
            thread_ = NULL;

            flow::case_stack_.teardown(shared_from_this());
            this->teardown();
        }

    protected:
        boost::thread* thread_;
    };
}

#endif  // X2BOOST_SINGLE_THREADED_FLOW_HPP_
<commit_msg>fixed build errors for g++<commit_after>// Copyright (c) 2014 Jae-jun Kang
// See the file COPYING for license details.

#ifndef X2BOOST_SINGLE_THREADED_FLOW_HPP_
#define X2BOOST_SINGLE_THREADED_FLOW_HPP_

#ifndef X2BOOST_PRE_HPP_
#include "x2boost/pre.hpp"
#endif

#include <boost/bind.hpp>
#include <boost/thread.hpp>

#include "x2boost/flows/event_based_flow.hpp"

namespace x2
{
    template<class Q = synchronized_event_queue>
    class X2BOOST_API single_threaded_flow : public event_based_flow<Q>
    {
    public:
        single_threaded_flow() : thread_(NULL) {}

        virtual ~single_threaded_flow() {}

        virtual void startup()
        {
            boost::mutex::scoped_lock lock(flow::mutex_);
            if (thread_) { return; }

            this->setup();
            flow::case_stack_.setup(boost::enable_shared_from_this<flow>::shared_from_this());

            thread_ = new boost::thread(boost::bind(&event_based_flow<Q>::run, this));
        }

        virtual void shutdown()
        {
            boost::mutex::scoped_lock lock(flow::mutex_);
            if (!thread_) { return; }

            // enqueue flow_stop
            event_based_flow<Q>::queue_.close();

            thread_->join();
            delete thread_;
            thread_ = NULL;

            flow::case_stack_.teardown(boost::enable_shared_from_this<flow>::shared_from_this());
            this->teardown();
        }

    protected:
        boost::thread* thread_;
    };
}

#endif  // X2BOOST_SINGLE_THREADED_FLOW_HPP_
<|endoftext|>


<commit_before>/* libwpd
 * Copyright (C) 2002 William Lachance (wrlach@gmail.com)
 * Copyright (C) 2002-2004 Marc Maurer (uwog@uwog.net)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 *
 * For further information visit http://libwpd.sourceforge.net
 */

/* "This product is not manufactured, approved, or supported by
 * Corel Corporation or Corel Corporation Limited."
 */

#include <stdio.h>
#include <stdarg.h>
#include "RawListener.h"

#define _U(M, L) \
	if (!m_printCallgraphScore) \
			__iuprintf M; \
	else \
		m_callStack.push(L);

#define _D(M, L) \
	if (!m_printCallgraphScore) \
			__idprintf M; \
	else \
	{ \
		ListenerCallback lc = m_callStack.top(); \
		if (lc != L) \
			m_callbackMisses++; \
		m_callStack.pop(); \
	}

RawListenerImpl::RawListenerImpl(bool printCallgraphScore) :
	m_indent(0),
	m_callbackMisses(0),
	m_printCallgraphScore(printCallgraphScore)
{
}

RawListenerImpl::~RawListenerImpl()
{
	if (m_printCallgraphScore)
		printf("%d\n", m_callStack.size() + m_callbackMisses);
}

void RawListenerImpl::__iprintf(const char *format, ...)
{
	if (m_printCallgraphScore) return;

	va_list args;
	va_start(args, format);
	for (int i=0; i<m_indent; i++)
		printf("  ");
	vprintf(format, args);
	va_end(args);
}

void RawListenerImpl::__iuprintf(const char *format, ...)
{
	va_list args;
	va_start(args, format);
	for (int i=0; i<m_indent; i++)
		printf("  ");
	vprintf(format, args);
	__indentUp();
	va_end(args);
}

void RawListenerImpl::__idprintf(const char *format, ...)
{
	va_list args;
	va_start(args, format);
	__indentDown();
	for (int i=0; i<m_indent; i++)
		printf("  ");
	vprintf(format, args);
	va_end(args);
}

WPXString getPropString(const WPXPropertyList &propList)
{
	WPXString propString;
	WPXPropertyList::Iter i(propList);
	if (!i.last())
	{
		WPXString prop;
		prop.sprintf("%s: %s", i.key(), i()->getStr().cstr());
		propString.append(prop);
		for (; i.next(); )
		{
			prop.sprintf(", %s: %s", i.key(), i()->getStr().cstr());
			propString.append(prop);
		}
	}

	return propString;
}

WPXString getPropString(const WPXPropertyListVector &itemList)
{
	WPXString propString;

	propString.append("(");
	WPXPropertyListVector::Iter i(itemList);

	if (!i.last())
	{
		propString.append("(");
		propString.append(getPropString(i()));
		propString.append(")");

		for (; i.next();)
		{
			propString.append(", (");
			propString.append(getPropString(i()));
			propString.append(")");
		}

	}
	propString.append(")");

	return propString;
}

void RawListenerImpl::setDocumentMetaData(const WPXPropertyList &propList)
{
	if (m_printCallgraphScore)
		return;

	__iprintf("setDocumentMetaData(%s)\n", getPropString(propList).cstr());
}

void RawListenerImpl::startDocument()
{
	_U(("startDocument()\n"), LC_START_DOCUMENT);
}

void RawListenerImpl::endDocument()
{
	_D(("endDocument()\n"), LC_START_DOCUMENT);
}

void RawListenerImpl::openPageSpan(const WPXPropertyList &propList)
{
	_U(("openPageSpan(%s)\n", getPropString(propList).cstr()),
	   LC_OPEN_PAGE_SPAN);
}

void RawListenerImpl::closePageSpan()
{
	_D(("closePageSpan()\n"),
		LC_OPEN_PAGE_SPAN);
}

void RawListenerImpl::openHeader(const WPXPropertyList &propList)
{
	_U(("openHeader(%s)\n",
	    getPropString(propList).cstr()),
	   LC_OPEN_HEADER_FOOTER);
}

void RawListenerImpl::closeHeader()
{
	_D(("closeHeader()\n"),
	   LC_OPEN_HEADER_FOOTER);
}

void RawListenerImpl::openFooter(const WPXPropertyList &propList)
{
	_U(("openFooter(%s)\n",
	    getPropString(propList).cstr()),
	   LC_OPEN_HEADER_FOOTER);
}

void RawListenerImpl::closeFooter()
{
	_D(("closeFooter()\n"),
	   LC_OPEN_HEADER_FOOTER);
}

void RawListenerImpl::openParagraph(const WPXPropertyList &propList, const WPXPropertyListVector &tabStops)
{
	_U(("openParagraph(%s, tab-stops: %s)\n", getPropString(propList).cstr(), getPropString(tabStops).cstr()),
	   LC_OPEN_PARAGRAPH);
}

void RawListenerImpl::closeParagraph()
{
	_D(("closeParagraph()\n"), LC_OPEN_PARAGRAPH);
}

void RawListenerImpl::openSpan(const WPXPropertyList &propList)
{
	_U(("openSpan(%s)\n", getPropString(propList).cstr()), LC_OPEN_SPAN);
}

void RawListenerImpl::closeSpan()
{
	_D(("closeSpan()\n"), LC_OPEN_SPAN);
}

void RawListenerImpl::openSection(const WPXPropertyList &propList, const WPXPropertyListVector &columns)
{
	_U(("openSection(%s, columns: %s)\n", getPropString(propList).cstr(), getPropString(columns).cstr()), LC_OPEN_SECTION);
}

void RawListenerImpl::closeSection()
{
	_D(("closeSection()\n"), LC_OPEN_SECTION);
}

void RawListenerImpl::insertTab()
{
	__iprintf("insertTab()\n");
}

void RawListenerImpl::insertText(const WPXString &text)
{
	WPXString textUTF8(text);
	__iprintf("insertText(text: %s)\n", textUTF8.cstr());
}

void RawListenerImpl::insertLineBreak()
{
	__iprintf("insertLineBreak()\n");
}

void RawListenerImpl::defineOrderedListLevel(const WPXPropertyList &propList)
{
	__iprintf("defineOrderedListLevel(%s)\n", getPropString(propList).cstr());
}

void RawListenerImpl::defineUnorderedListLevel(const WPXPropertyList &propList)
{
	__iprintf("defineUnorderedListLevel(%s)\n", getPropString(propList).cstr());
}

void RawListenerImpl::openOrderedListLevel(const WPXPropertyList &propList)
{
	_U(("openOrderedListLevel(%s)\n", getPropString(propList).cstr()),
	   LC_OPEN_ORDERED_LIST_LEVEL);
}

void RawListenerImpl::openUnorderedListLevel(const WPXPropertyList &propList)
{
	_U(("openUnorderedListLevel(%s)\n", getPropString(propList).cstr()),
	   LC_OPEN_UNORDERED_LIST_LEVEL);
}

void RawListenerImpl::closeOrderedListLevel()
{
	_D(("closeOrderedListLevel()\n"),
	   LC_OPEN_ORDERED_LIST_LEVEL);
}

void RawListenerImpl::closeUnorderedListLevel()
{
	_D(("closeUnorderedListLevel()\n"), LC_OPEN_UNORDERED_LIST_LEVEL);
}

void RawListenerImpl::openListElement(const WPXPropertyList &propList, const WPXPropertyListVector &tabStops)
{
	_U(("openListElement(%s, tab-stops: %s)\n", getPropString(propList).cstr(), getPropString(tabStops).cstr()),
	   LC_OPEN_LIST_ELEMENT);
}

void RawListenerImpl::closeListElement()
{
	_D(("closeListElement()\n"), LC_OPEN_LIST_ELEMENT);
}

void RawListenerImpl::openFootnote(const WPXPropertyList &propList)
{
	_U(("openFootnote(%s)\n", getPropString(propList).cstr()),
	   LC_OPEN_FOOTNOTE);
}

void RawListenerImpl::closeFootnote()
{
	_D(("closeFootnote()\n"), LC_OPEN_FOOTNOTE);
}

void RawListenerImpl::openEndnote(const WPXPropertyList &propList)
{
	_U(("openEndnote(number: %s)\n", getPropString(propList).cstr()),
	   LC_OPEN_ENDNOTE);
}

void RawListenerImpl::closeEndnote()
{
	_D(("closeEndnote()\n"), LC_OPEN_ENDNOTE);
}

void RawListenerImpl::openTable(const WPXPropertyList &propList, const WPXPropertyListVector &columns)
{
	_U(("openTable(%s, columns: %s)\n", getPropString(propList).cstr(), getPropString(columns).cstr()), LC_OPEN_TABLE);
}

void RawListenerImpl::openTableRow(const WPXPropertyList &propList)
{
	_U(("openTableRow(%s)\n", getPropString(propList).cstr()),
	   LC_OPEN_TABLE_ROW);
}

void RawListenerImpl::closeTableRow()
{
	_D(("closeTableRow()\n"), LC_OPEN_TABLE_ROW);
}

void RawListenerImpl::openTableCell(const WPXPropertyList &propList)
{
	_U(("openTableCell(%s)\n", getPropString(propList).cstr()),
	   LC_OPEN_TABLE_CELL);
}

void RawListenerImpl::closeTableCell()
{
	_D(("closeTableCell()\n"), LC_OPEN_TABLE_CELL);
}

void RawListenerImpl::insertCoveredTableCell(const WPXPropertyList &propList)
{
	__iprintf("insertCoveredTableCell(%s)\n", getPropString(propList).cstr());
}

void RawListenerImpl::closeTable()
{
	_D(("closeTable()\n"), LC_OPEN_TABLE);
}
<commit_msg>one more warning, this time on x86_64<commit_after>/* libwpd
 * Copyright (C) 2002 William Lachance (wrlach@gmail.com)
 * Copyright (C) 2002-2004 Marc Maurer (uwog@uwog.net)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 *
 * For further information visit http://libwpd.sourceforge.net
 */

/* "This product is not manufactured, approved, or supported by
 * Corel Corporation or Corel Corporation Limited."
 */

#include <stdio.h>
#include <stdarg.h>
#include "RawListener.h"

#define _U(M, L) \
	if (!m_printCallgraphScore) \
			__iuprintf M; \
	else \
		m_callStack.push(L);

#define _D(M, L) \
	if (!m_printCallgraphScore) \
			__idprintf M; \
	else \
	{ \
		ListenerCallback lc = m_callStack.top(); \
		if (lc != L) \
			m_callbackMisses++; \
		m_callStack.pop(); \
	}

RawListenerImpl::RawListenerImpl(bool printCallgraphScore) :
	m_indent(0),
	m_callbackMisses(0),
	m_printCallgraphScore(printCallgraphScore)
{
}

RawListenerImpl::~RawListenerImpl()
{
	if (m_printCallgraphScore)
		printf("%d\n", (int)(m_callStack.size() + m_callbackMisses));
}

void RawListenerImpl::__iprintf(const char *format, ...)
{
	if (m_printCallgraphScore) return;

	va_list args;
	va_start(args, format);
	for (int i=0; i<m_indent; i++)
		printf("  ");
	vprintf(format, args);
	va_end(args);
}

void RawListenerImpl::__iuprintf(const char *format, ...)
{
	va_list args;
	va_start(args, format);
	for (int i=0; i<m_indent; i++)
		printf("  ");
	vprintf(format, args);
	__indentUp();
	va_end(args);
}

void RawListenerImpl::__idprintf(const char *format, ...)
{
	va_list args;
	va_start(args, format);
	__indentDown();
	for (int i=0; i<m_indent; i++)
		printf("  ");
	vprintf(format, args);
	va_end(args);
}

WPXString getPropString(const WPXPropertyList &propList)
{
	WPXString propString;
	WPXPropertyList::Iter i(propList);
	if (!i.last())
	{
		WPXString prop;
		prop.sprintf("%s: %s", i.key(), i()->getStr().cstr());
		propString.append(prop);
		for (; i.next(); )
		{
			prop.sprintf(", %s: %s", i.key(), i()->getStr().cstr());
			propString.append(prop);
		}
	}

	return propString;
}

WPXString getPropString(const WPXPropertyListVector &itemList)
{
	WPXString propString;

	propString.append("(");
	WPXPropertyListVector::Iter i(itemList);

	if (!i.last())
	{
		propString.append("(");
		propString.append(getPropString(i()));
		propString.append(")");

		for (; i.next();)
		{
			propString.append(", (");
			propString.append(getPropString(i()));
			propString.append(")");
		}

	}
	propString.append(")");

	return propString;
}

void RawListenerImpl::setDocumentMetaData(const WPXPropertyList &propList)
{
	if (m_printCallgraphScore)
		return;

	__iprintf("setDocumentMetaData(%s)\n", getPropString(propList).cstr());
}

void RawListenerImpl::startDocument()
{
	_U(("startDocument()\n"), LC_START_DOCUMENT);
}

void RawListenerImpl::endDocument()
{
	_D(("endDocument()\n"), LC_START_DOCUMENT);
}

void RawListenerImpl::openPageSpan(const WPXPropertyList &propList)
{
	_U(("openPageSpan(%s)\n", getPropString(propList).cstr()),
	   LC_OPEN_PAGE_SPAN);
}

void RawListenerImpl::closePageSpan()
{
	_D(("closePageSpan()\n"),
		LC_OPEN_PAGE_SPAN);
}

void RawListenerImpl::openHeader(const WPXPropertyList &propList)
{
	_U(("openHeader(%s)\n",
	    getPropString(propList).cstr()),
	   LC_OPEN_HEADER_FOOTER);
}

void RawListenerImpl::closeHeader()
{
	_D(("closeHeader()\n"),
	   LC_OPEN_HEADER_FOOTER);
}

void RawListenerImpl::openFooter(const WPXPropertyList &propList)
{
	_U(("openFooter(%s)\n",
	    getPropString(propList).cstr()),
	   LC_OPEN_HEADER_FOOTER);
}

void RawListenerImpl::closeFooter()
{
	_D(("closeFooter()\n"),
	   LC_OPEN_HEADER_FOOTER);
}

void RawListenerImpl::openParagraph(const WPXPropertyList &propList, const WPXPropertyListVector &tabStops)
{
	_U(("openParagraph(%s, tab-stops: %s)\n", getPropString(propList).cstr(), getPropString(tabStops).cstr()),
	   LC_OPEN_PARAGRAPH);
}

void RawListenerImpl::closeParagraph()
{
	_D(("closeParagraph()\n"), LC_OPEN_PARAGRAPH);
}

void RawListenerImpl::openSpan(const WPXPropertyList &propList)
{
	_U(("openSpan(%s)\n", getPropString(propList).cstr()), LC_OPEN_SPAN);
}

void RawListenerImpl::closeSpan()
{
	_D(("closeSpan()\n"), LC_OPEN_SPAN);
}

void RawListenerImpl::openSection(const WPXPropertyList &propList, const WPXPropertyListVector &columns)
{
	_U(("openSection(%s, columns: %s)\n", getPropString(propList).cstr(), getPropString(columns).cstr()), LC_OPEN_SECTION);
}

void RawListenerImpl::closeSection()
{
	_D(("closeSection()\n"), LC_OPEN_SECTION);
}

void RawListenerImpl::insertTab()
{
	__iprintf("insertTab()\n");
}

void RawListenerImpl::insertText(const WPXString &text)
{
	WPXString textUTF8(text);
	__iprintf("insertText(text: %s)\n", textUTF8.cstr());
}

void RawListenerImpl::insertLineBreak()
{
	__iprintf("insertLineBreak()\n");
}

void RawListenerImpl::defineOrderedListLevel(const WPXPropertyList &propList)
{
	__iprintf("defineOrderedListLevel(%s)\n", getPropString(propList).cstr());
}

void RawListenerImpl::defineUnorderedListLevel(const WPXPropertyList &propList)
{
	__iprintf("defineUnorderedListLevel(%s)\n", getPropString(propList).cstr());
}

void RawListenerImpl::openOrderedListLevel(const WPXPropertyList &propList)
{
	_U(("openOrderedListLevel(%s)\n", getPropString(propList).cstr()),
	   LC_OPEN_ORDERED_LIST_LEVEL);
}

void RawListenerImpl::openUnorderedListLevel(const WPXPropertyList &propList)
{
	_U(("openUnorderedListLevel(%s)\n", getPropString(propList).cstr()),
	   LC_OPEN_UNORDERED_LIST_LEVEL);
}

void RawListenerImpl::closeOrderedListLevel()
{
	_D(("closeOrderedListLevel()\n"),
	   LC_OPEN_ORDERED_LIST_LEVEL);
}

void RawListenerImpl::closeUnorderedListLevel()
{
	_D(("closeUnorderedListLevel()\n"), LC_OPEN_UNORDERED_LIST_LEVEL);
}

void RawListenerImpl::openListElement(const WPXPropertyList &propList, const WPXPropertyListVector &tabStops)
{
	_U(("openListElement(%s, tab-stops: %s)\n", getPropString(propList).cstr(), getPropString(tabStops).cstr()),
	   LC_OPEN_LIST_ELEMENT);
}

void RawListenerImpl::closeListElement()
{
	_D(("closeListElement()\n"), LC_OPEN_LIST_ELEMENT);
}

void RawListenerImpl::openFootnote(const WPXPropertyList &propList)
{
	_U(("openFootnote(%s)\n", getPropString(propList).cstr()),
	   LC_OPEN_FOOTNOTE);
}

void RawListenerImpl::closeFootnote()
{
	_D(("closeFootnote()\n"), LC_OPEN_FOOTNOTE);
}

void RawListenerImpl::openEndnote(const WPXPropertyList &propList)
{
	_U(("openEndnote(number: %s)\n", getPropString(propList).cstr()),
	   LC_OPEN_ENDNOTE);
}

void RawListenerImpl::closeEndnote()
{
	_D(("closeEndnote()\n"), LC_OPEN_ENDNOTE);
}

void RawListenerImpl::openTable(const WPXPropertyList &propList, const WPXPropertyListVector &columns)
{
	_U(("openTable(%s, columns: %s)\n", getPropString(propList).cstr(), getPropString(columns).cstr()), LC_OPEN_TABLE);
}

void RawListenerImpl::openTableRow(const WPXPropertyList &propList)
{
	_U(("openTableRow(%s)\n", getPropString(propList).cstr()),
	   LC_OPEN_TABLE_ROW);
}

void RawListenerImpl::closeTableRow()
{
	_D(("closeTableRow()\n"), LC_OPEN_TABLE_ROW);
}

void RawListenerImpl::openTableCell(const WPXPropertyList &propList)
{
	_U(("openTableCell(%s)\n", getPropString(propList).cstr()),
	   LC_OPEN_TABLE_CELL);
}

void RawListenerImpl::closeTableCell()
{
	_D(("closeTableCell()\n"), LC_OPEN_TABLE_CELL);
}

void RawListenerImpl::insertCoveredTableCell(const WPXPropertyList &propList)
{
	__iprintf("insertCoveredTableCell(%s)\n", getPropString(propList).cstr());
}

void RawListenerImpl::closeTable()
{
	_D(("closeTable()\n"), LC_OPEN_TABLE);
}
<|endoftext|>


<commit_before>/*
 * Copyright 2017 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkArenaAlloc.h"
#include "SkAutoBlitterChoose.h"
#include "SkComposeShader.h"
#include "SkDraw.h"
#include "SkNx.h"
#include "SkPM4fPriv.h"
#include "SkRasterClip.h"
#include "SkScan.h"
#include "SkShaderBase.h"
#include "SkString.h"
#include "SkVertState.h"

#include "SkArenaAlloc.h"
#include "SkCoreBlitters.h"
#include "SkColorSpaceXform.h"
#include "SkColorSpace_Base.h"

struct Matrix43 {
    float fMat[12];    // column major

    Sk4f map(float x, float y) const {
        return Sk4f::Load(&fMat[0]) * x + Sk4f::Load(&fMat[4]) * y + Sk4f::Load(&fMat[8]);
    }

    void setConcat(const Matrix43& a, const SkMatrix& b) {
        fMat[ 0] = a.dot(0, b.getScaleX(), b.getSkewY());
        fMat[ 1] = a.dot(1, b.getScaleX(), b.getSkewY());
        fMat[ 2] = a.dot(2, b.getScaleX(), b.getSkewY());
        fMat[ 3] = a.dot(3, b.getScaleX(), b.getSkewY());

        fMat[ 4] = a.dot(0, b.getSkewX(), b.getScaleY());
        fMat[ 5] = a.dot(1, b.getSkewX(), b.getScaleY());
        fMat[ 6] = a.dot(2, b.getSkewX(), b.getScaleY());
        fMat[ 7] = a.dot(3, b.getSkewX(), b.getScaleY());

        fMat[ 8] = a.dot(0, b.getTranslateX(), b.getTranslateY()) + a.fMat[ 8];
        fMat[ 9] = a.dot(1, b.getTranslateX(), b.getTranslateY()) + a.fMat[ 9];
        fMat[10] = a.dot(2, b.getTranslateX(), b.getTranslateY()) + a.fMat[10];
        fMat[11] = a.dot(3, b.getTranslateX(), b.getTranslateY()) + a.fMat[11];
    }

private:
    float dot(int index, float x, float y) const {
        return fMat[index + 0] * x + fMat[index + 4] * y;
    }
};

static SkScan::HairRCProc ChooseHairProc(bool doAntiAlias) {
    return doAntiAlias ? SkScan::AntiHairLine : SkScan::HairLine;
}

static bool texture_to_matrix(const VertState& state, const SkPoint verts[],
                              const SkPoint texs[], SkMatrix* matrix) {
    SkPoint src[3], dst[3];

    src[0] = texs[state.f0];
    src[1] = texs[state.f1];
    src[2] = texs[state.f2];
    dst[0] = verts[state.f0];
    dst[1] = verts[state.f1];
    dst[2] = verts[state.f2];
    return matrix->setPolyToPoly(src, dst, 3);
}

class SkTriColorShader : public SkShaderBase {
public:
    SkTriColorShader(bool isOpaque) : fIsOpaque(isOpaque) {}

    Matrix43* getMatrix43() { return &fM43; }

    bool isOpaque() const override { return fIsOpaque; }

    SK_TO_STRING_OVERRIDE()

    // For serialization.  This will never be called.
    Factory getFactory() const override { SK_ABORT("not reached"); return nullptr; }

protected:
    Context* onMakeContext(const ContextRec& rec, SkArenaAlloc* alloc) const override {
        return nullptr;
    }
    bool onAppendStages(const StageRec& rec) const override {
        rec.fPipeline->append_seed_shader();
        rec.fPipeline->append(SkRasterPipeline::matrix_4x3, &fM43);
        // In theory we should never need to clamp. However, either due to imprecision in our
        // matrix43, or the scan converter passing us pixel centers that in fact are not within
        // the triangle, we do see occasional (slightly) out-of-range values, so we add these
        // clamp stages. It would be nice to find a way to detect when these are not needed.
        rec.fPipeline->append(SkRasterPipeline::clamp_0);
        rec.fPipeline->append(SkRasterPipeline::clamp_a);
        return true;
    }

private:
    Matrix43 fM43;
    const bool fIsOpaque;

    typedef SkShaderBase INHERITED;
};

#ifndef SK_IGNORE_TO_STRING
void SkTriColorShader::toString(SkString* str) const {
    str->append("SkTriColorShader: (");

    this->INHERITED::toString(str);

    str->append(")");
}
#endif

static bool update_tricolor_matrix(const SkMatrix& ctmInv,
                                   const SkPoint pts[], const SkPM4f colors[],
                                   int index0, int index1, int index2, Matrix43* result) {
    SkMatrix m, im;
    m.reset();
    m.set(0, pts[index1].fX - pts[index0].fX);
    m.set(1, pts[index2].fX - pts[index0].fX);
    m.set(2, pts[index0].fX);
    m.set(3, pts[index1].fY - pts[index0].fY);
    m.set(4, pts[index2].fY - pts[index0].fY);
    m.set(5, pts[index0].fY);
    if (!m.invert(&im)) {
        return false;
    }

    SkMatrix dstToUnit;
    dstToUnit.setConcat(im, ctmInv);

    Sk4f c0 = colors[index0].to4f(),
         c1 = colors[index1].to4f(),
         c2 = colors[index2].to4f();

    Matrix43 colorm;
    (c1 - c0).store(&colorm.fMat[0]);
    (c2 - c0).store(&colorm.fMat[4]);
    c0.store(&colorm.fMat[8]);
    result->setConcat(colorm, dstToUnit);
    return true;
}

// Convert the SkColors into float colors. The conversion depends on some conditions:
// - If the pixmap has a dst colorspace, we have to be "color-correct".
//   Do we map into dst-colorspace before or after we interpolate?
// - We have to decide when to apply per-color alpha (before or after we interpolate)
//
// For now, we will take a simple approach, but recognize this is just a start:
// - convert colors into dst colorspace before interpolation (matches gradients)
// - apply per-color alpha before interpolation (matches old version of vertices)
//
static SkPM4f* convert_colors(const SkColor src[], int count, SkColorSpace* deviceCS,
                              SkArenaAlloc* alloc) {
    SkPM4f* dst = alloc->makeArray<SkPM4f>(count);
    if (!deviceCS) {
        for (int i = 0; i < count; ++i) {
            dst[i] = SkPM4f_from_SkColor(src[i], nullptr);
        }
    } else {
        auto srcCS = SkColorSpace::MakeSRGB();
        auto dstCS = deviceCS->makeLinearGamma();
        SkColorSpaceXform::Apply(dstCS.get(), SkColorSpaceXform::kRGBA_F32_ColorFormat, dst,
                                 srcCS.get(), SkColorSpaceXform::kBGRA_8888_ColorFormat, src,
                                 count, SkColorSpaceXform::kPremul_AlphaOp);
    }
    return dst;
}

static bool compute_is_opaque(const SkColor colors[], int count) {
    uint32_t c = ~0;
    for (int i = 0; i < count; ++i) {
        c &= colors[i];
    }
    return SkColorGetA(c) == 0xFF;
}

void SkDraw::drawVertices(SkVertices::VertexMode vmode, int count,
                          const SkPoint vertices[], const SkPoint textures[],
                          const SkColor colors[], SkBlendMode bmode,
                          const uint16_t indices[], int indexCount,
                          const SkPaint& paint) const {
    SkASSERT(0 == count || vertices);

    // abort early if there is nothing to draw
    if (count < 3 || (indices && indexCount < 3) || fRC->isEmpty()) {
        return;
    }
    SkMatrix ctmInv;
    if (!fMatrix->invert(&ctmInv)) {
        return;
    }

    // make textures and shader mutually consistent
    SkShader* shader = paint.getShader();
    if (!(shader && textures)) {
        shader = nullptr;
        textures = nullptr;
    }

    // We can simplify things for certain blendmodes. This is for speed, and SkComposeShader
    // itself insists we don't pass kSrc or kDst to it.
    //
    if (colors && textures) {
        switch (bmode) {
            case SkBlendMode::kSrc:
                colors = nullptr;
                break;
            case SkBlendMode::kDst:
                textures = nullptr;
                break;
            default: break;
        }
    }

    // we don't use the shader if there are no textures
    if (!textures) {
        shader = nullptr;
    }

    constexpr size_t defCount = 16;
    constexpr size_t outerSize = sizeof(SkTriColorShader) +
                                 sizeof(SkComposeShader) +
                                 (sizeof(SkPoint) + sizeof(SkPM4f)) * defCount;
    SkSTArenaAlloc<outerSize> outerAlloc;

    SkPoint* devVerts = outerAlloc.makeArray<SkPoint>(count);
    fMatrix->mapPoints(devVerts, vertices, count);

    VertState       state(count, indices, indexCount);
    VertState::Proc vertProc = state.chooseProc(vmode);

    if (colors || textures) {
        SkPM4f*     dstColors = nullptr;
        Matrix43*   matrix43 = nullptr;

        if (colors) {
            dstColors = convert_colors(colors, count, fDst.colorSpace(), &outerAlloc);

            SkTriColorShader* triShader = outerAlloc.make<SkTriColorShader>(
                                                                compute_is_opaque(colors, count));
            matrix43 = triShader->getMatrix43();
            if (shader) {
                shader = outerAlloc.make<SkComposeShader>(sk_ref_sp(triShader), sk_ref_sp(shader),
                                                          bmode, 1);
            } else {
                shader = triShader;
            }
        }

        SkPaint p(paint);
        p.setShader(sk_ref_sp(shader));

        if (!textures) {    // only tricolor shader
            SkASSERT(matrix43);
            auto blitter = SkCreateRasterPipelineBlitter(fDst, p, *fMatrix, &outerAlloc);
            while (vertProc(&state)) {
                if (!update_tricolor_matrix(ctmInv, vertices, dstColors,
                                            state.f0, state.f1, state.f2,
                                            matrix43)) {
                    continue;
                }

                SkPoint tmp[] = {
                    devVerts[state.f0], devVerts[state.f1], devVerts[state.f2]
                };
                SkScan::FillTriangle(tmp, *fRC, blitter);
            }
        } else {
            while (vertProc(&state)) {
                SkSTArenaAlloc<2048> innerAlloc;

                const SkMatrix* ctm = fMatrix;
                SkMatrix tmpCtm;
                if (textures) {
                    SkMatrix localM;
                    texture_to_matrix(state, vertices, textures, &localM);
                    tmpCtm = SkMatrix::Concat(*fMatrix, localM);
                    ctm = &tmpCtm;
                }

                if (matrix43 && !update_tricolor_matrix(ctmInv, vertices, dstColors,
                                                        state.f0, state.f1, state.f2,
                                                        matrix43)) {
                    continue;
                }

                SkPoint tmp[] = {
                    devVerts[state.f0], devVerts[state.f1], devVerts[state.f2]
                };
                auto blitter = SkCreateRasterPipelineBlitter(fDst, p, *ctm, &innerAlloc);
                SkScan::FillTriangle(tmp, *fRC, blitter);
            }
        }
    } else {
        // no colors[] and no texture, stroke hairlines with paint's color.
        SkPaint p;
        p.setStyle(SkPaint::kStroke_Style);
        SkAutoBlitterChoose blitter(fDst, *fMatrix, p);
        // Abort early if we failed to create a shader context.
        if (blitter->isNullBlitter()) {
            return;
        }
        SkScan::HairRCProc hairProc = ChooseHairProc(paint.isAntiAlias());
        const SkRasterClip& clip = *fRC;
        while (vertProc(&state)) {
            SkPoint array[] = {
                devVerts[state.f0], devVerts[state.f1], devVerts[state.f2], devVerts[state.f0]
            };
            hairProc(array, 4, clip, blitter.get());
        }
    }
}
<commit_msg>Remove another stray pair of clamps.<commit_after>/*
 * Copyright 2017 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkArenaAlloc.h"
#include "SkAutoBlitterChoose.h"
#include "SkComposeShader.h"
#include "SkDraw.h"
#include "SkNx.h"
#include "SkPM4fPriv.h"
#include "SkRasterClip.h"
#include "SkScan.h"
#include "SkShaderBase.h"
#include "SkString.h"
#include "SkVertState.h"

#include "SkArenaAlloc.h"
#include "SkCoreBlitters.h"
#include "SkColorSpaceXform.h"
#include "SkColorSpace_Base.h"

struct Matrix43 {
    float fMat[12];    // column major

    Sk4f map(float x, float y) const {
        return Sk4f::Load(&fMat[0]) * x + Sk4f::Load(&fMat[4]) * y + Sk4f::Load(&fMat[8]);
    }

    void setConcat(const Matrix43& a, const SkMatrix& b) {
        fMat[ 0] = a.dot(0, b.getScaleX(), b.getSkewY());
        fMat[ 1] = a.dot(1, b.getScaleX(), b.getSkewY());
        fMat[ 2] = a.dot(2, b.getScaleX(), b.getSkewY());
        fMat[ 3] = a.dot(3, b.getScaleX(), b.getSkewY());

        fMat[ 4] = a.dot(0, b.getSkewX(), b.getScaleY());
        fMat[ 5] = a.dot(1, b.getSkewX(), b.getScaleY());
        fMat[ 6] = a.dot(2, b.getSkewX(), b.getScaleY());
        fMat[ 7] = a.dot(3, b.getSkewX(), b.getScaleY());

        fMat[ 8] = a.dot(0, b.getTranslateX(), b.getTranslateY()) + a.fMat[ 8];
        fMat[ 9] = a.dot(1, b.getTranslateX(), b.getTranslateY()) + a.fMat[ 9];
        fMat[10] = a.dot(2, b.getTranslateX(), b.getTranslateY()) + a.fMat[10];
        fMat[11] = a.dot(3, b.getTranslateX(), b.getTranslateY()) + a.fMat[11];
    }

private:
    float dot(int index, float x, float y) const {
        return fMat[index + 0] * x + fMat[index + 4] * y;
    }
};

static SkScan::HairRCProc ChooseHairProc(bool doAntiAlias) {
    return doAntiAlias ? SkScan::AntiHairLine : SkScan::HairLine;
}

static bool texture_to_matrix(const VertState& state, const SkPoint verts[],
                              const SkPoint texs[], SkMatrix* matrix) {
    SkPoint src[3], dst[3];

    src[0] = texs[state.f0];
    src[1] = texs[state.f1];
    src[2] = texs[state.f2];
    dst[0] = verts[state.f0];
    dst[1] = verts[state.f1];
    dst[2] = verts[state.f2];
    return matrix->setPolyToPoly(src, dst, 3);
}

class SkTriColorShader : public SkShaderBase {
public:
    SkTriColorShader(bool isOpaque) : fIsOpaque(isOpaque) {}

    Matrix43* getMatrix43() { return &fM43; }

    bool isOpaque() const override { return fIsOpaque; }

    SK_TO_STRING_OVERRIDE()

    // For serialization.  This will never be called.
    Factory getFactory() const override { SK_ABORT("not reached"); return nullptr; }

protected:
    Context* onMakeContext(const ContextRec& rec, SkArenaAlloc* alloc) const override {
        return nullptr;
    }
    bool onAppendStages(const StageRec& rec) const override {
        rec.fPipeline->append_seed_shader();
        rec.fPipeline->append(SkRasterPipeline::matrix_4x3, &fM43);
        return true;
    }

private:
    Matrix43 fM43;
    const bool fIsOpaque;

    typedef SkShaderBase INHERITED;
};

#ifndef SK_IGNORE_TO_STRING
void SkTriColorShader::toString(SkString* str) const {
    str->append("SkTriColorShader: (");

    this->INHERITED::toString(str);

    str->append(")");
}
#endif

static bool update_tricolor_matrix(const SkMatrix& ctmInv,
                                   const SkPoint pts[], const SkPM4f colors[],
                                   int index0, int index1, int index2, Matrix43* result) {
    SkMatrix m, im;
    m.reset();
    m.set(0, pts[index1].fX - pts[index0].fX);
    m.set(1, pts[index2].fX - pts[index0].fX);
    m.set(2, pts[index0].fX);
    m.set(3, pts[index1].fY - pts[index0].fY);
    m.set(4, pts[index2].fY - pts[index0].fY);
    m.set(5, pts[index0].fY);
    if (!m.invert(&im)) {
        return false;
    }

    SkMatrix dstToUnit;
    dstToUnit.setConcat(im, ctmInv);

    Sk4f c0 = colors[index0].to4f(),
         c1 = colors[index1].to4f(),
         c2 = colors[index2].to4f();

    Matrix43 colorm;
    (c1 - c0).store(&colorm.fMat[0]);
    (c2 - c0).store(&colorm.fMat[4]);
    c0.store(&colorm.fMat[8]);
    result->setConcat(colorm, dstToUnit);
    return true;
}

// Convert the SkColors into float colors. The conversion depends on some conditions:
// - If the pixmap has a dst colorspace, we have to be "color-correct".
//   Do we map into dst-colorspace before or after we interpolate?
// - We have to decide when to apply per-color alpha (before or after we interpolate)
//
// For now, we will take a simple approach, but recognize this is just a start:
// - convert colors into dst colorspace before interpolation (matches gradients)
// - apply per-color alpha before interpolation (matches old version of vertices)
//
static SkPM4f* convert_colors(const SkColor src[], int count, SkColorSpace* deviceCS,
                              SkArenaAlloc* alloc) {
    SkPM4f* dst = alloc->makeArray<SkPM4f>(count);
    if (!deviceCS) {
        for (int i = 0; i < count; ++i) {
            dst[i] = SkPM4f_from_SkColor(src[i], nullptr);
        }
    } else {
        auto srcCS = SkColorSpace::MakeSRGB();
        auto dstCS = deviceCS->makeLinearGamma();
        SkColorSpaceXform::Apply(dstCS.get(), SkColorSpaceXform::kRGBA_F32_ColorFormat, dst,
                                 srcCS.get(), SkColorSpaceXform::kBGRA_8888_ColorFormat, src,
                                 count, SkColorSpaceXform::kPremul_AlphaOp);
    }
    return dst;
}

static bool compute_is_opaque(const SkColor colors[], int count) {
    uint32_t c = ~0;
    for (int i = 0; i < count; ++i) {
        c &= colors[i];
    }
    return SkColorGetA(c) == 0xFF;
}

void SkDraw::drawVertices(SkVertices::VertexMode vmode, int count,
                          const SkPoint vertices[], const SkPoint textures[],
                          const SkColor colors[], SkBlendMode bmode,
                          const uint16_t indices[], int indexCount,
                          const SkPaint& paint) const {
    SkASSERT(0 == count || vertices);

    // abort early if there is nothing to draw
    if (count < 3 || (indices && indexCount < 3) || fRC->isEmpty()) {
        return;
    }
    SkMatrix ctmInv;
    if (!fMatrix->invert(&ctmInv)) {
        return;
    }

    // make textures and shader mutually consistent
    SkShader* shader = paint.getShader();
    if (!(shader && textures)) {
        shader = nullptr;
        textures = nullptr;
    }

    // We can simplify things for certain blendmodes. This is for speed, and SkComposeShader
    // itself insists we don't pass kSrc or kDst to it.
    //
    if (colors && textures) {
        switch (bmode) {
            case SkBlendMode::kSrc:
                colors = nullptr;
                break;
            case SkBlendMode::kDst:
                textures = nullptr;
                break;
            default: break;
        }
    }

    // we don't use the shader if there are no textures
    if (!textures) {
        shader = nullptr;
    }

    constexpr size_t defCount = 16;
    constexpr size_t outerSize = sizeof(SkTriColorShader) +
                                 sizeof(SkComposeShader) +
                                 (sizeof(SkPoint) + sizeof(SkPM4f)) * defCount;
    SkSTArenaAlloc<outerSize> outerAlloc;

    SkPoint* devVerts = outerAlloc.makeArray<SkPoint>(count);
    fMatrix->mapPoints(devVerts, vertices, count);

    VertState       state(count, indices, indexCount);
    VertState::Proc vertProc = state.chooseProc(vmode);

    if (colors || textures) {
        SkPM4f*     dstColors = nullptr;
        Matrix43*   matrix43 = nullptr;

        if (colors) {
            dstColors = convert_colors(colors, count, fDst.colorSpace(), &outerAlloc);

            SkTriColorShader* triShader = outerAlloc.make<SkTriColorShader>(
                                                                compute_is_opaque(colors, count));
            matrix43 = triShader->getMatrix43();
            if (shader) {
                shader = outerAlloc.make<SkComposeShader>(sk_ref_sp(triShader), sk_ref_sp(shader),
                                                          bmode, 1);
            } else {
                shader = triShader;
            }
        }

        SkPaint p(paint);
        p.setShader(sk_ref_sp(shader));

        if (!textures) {    // only tricolor shader
            SkASSERT(matrix43);
            auto blitter = SkCreateRasterPipelineBlitter(fDst, p, *fMatrix, &outerAlloc);
            while (vertProc(&state)) {
                if (!update_tricolor_matrix(ctmInv, vertices, dstColors,
                                            state.f0, state.f1, state.f2,
                                            matrix43)) {
                    continue;
                }

                SkPoint tmp[] = {
                    devVerts[state.f0], devVerts[state.f1], devVerts[state.f2]
                };
                SkScan::FillTriangle(tmp, *fRC, blitter);
            }
        } else {
            while (vertProc(&state)) {
                SkSTArenaAlloc<2048> innerAlloc;

                const SkMatrix* ctm = fMatrix;
                SkMatrix tmpCtm;
                if (textures) {
                    SkMatrix localM;
                    texture_to_matrix(state, vertices, textures, &localM);
                    tmpCtm = SkMatrix::Concat(*fMatrix, localM);
                    ctm = &tmpCtm;
                }

                if (matrix43 && !update_tricolor_matrix(ctmInv, vertices, dstColors,
                                                        state.f0, state.f1, state.f2,
                                                        matrix43)) {
                    continue;
                }

                SkPoint tmp[] = {
                    devVerts[state.f0], devVerts[state.f1], devVerts[state.f2]
                };
                auto blitter = SkCreateRasterPipelineBlitter(fDst, p, *ctm, &innerAlloc);
                SkScan::FillTriangle(tmp, *fRC, blitter);
            }
        }
    } else {
        // no colors[] and no texture, stroke hairlines with paint's color.
        SkPaint p;
        p.setStyle(SkPaint::kStroke_Style);
        SkAutoBlitterChoose blitter(fDst, *fMatrix, p);
        // Abort early if we failed to create a shader context.
        if (blitter->isNullBlitter()) {
            return;
        }
        SkScan::HairRCProc hairProc = ChooseHairProc(paint.isAntiAlias());
        const SkRasterClip& clip = *fRC;
        while (vertProc(&state)) {
            SkPoint array[] = {
                devVerts[state.f0], devVerts[state.f1], devVerts[state.f2], devVerts[state.f0]
            };
            hairProc(array, 4, clip, blitter.get());
        }
    }
}
<|endoftext|>


<commit_before>/*
 *
 * Copyright 2017 gRPC authors.
 *
 * 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 "src/core/lib/support/fork.h"

#include <string.h>

#include <grpc/support/alloc.h>
#include <grpc/support/useful.h>

#include "src/core/lib/support/env.h"

/*
 * NOTE: FORKING IS NOT GENERALLY SUPPORTED, THIS IS ONLY INTENDED TO WORK
 *       AROUND VERY SPECIFIC USE CASES.
 */

static int override_fork_support_enabled = -1;
static int fork_support_enabled;

void grpc_fork_support_init() {
#ifdef GRPC_ENABLE_FORK_SUPPORT
  fork_support_enabled = 1;
#else
  fork_support_enabled = 0;
  char* env = gpr_getenv("GRPC_ENABLE_FORK_SUPPORT");
  if (env != nullptr) {
    static const char* truthy[] = {"yes",  "Yes",  "YES", "true",
                                   "True", "TRUE", "1"};
    for (size_t i = 0; i < GPR_ARRAY_SIZE(truthy); i++) {
      if (0 == strcmp(env, truthy[i])) {
        fork_support_enabled = 1;
      }
    }
    gpr_free(env);
  }
#endif
  if (override_fork_support_enabled != -1) {
    fork_support_enabled = override_fork_support_enabled;
  }
}

int grpc_fork_support_enabled() { return fork_support_enabled; }

void grpc_enable_fork_support(int enable) {
  override_fork_support_enabled = enable;
}
<commit_msg>Allow turning off fork support with env variable<commit_after>/*
 *
 * Copyright 2017 gRPC authors.
 *
 * 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 "src/core/lib/support/fork.h"

#include <string.h>

#include <grpc/support/alloc.h>
#include <grpc/support/useful.h>

#include "src/core/lib/support/env.h"

/*
 * NOTE: FORKING IS NOT GENERALLY SUPPORTED, THIS IS ONLY INTENDED TO WORK
 *       AROUND VERY SPECIFIC USE CASES.
 */

static int override_fork_support_enabled = -1;
static int fork_support_enabled;

void grpc_fork_support_init() {
#ifdef GRPC_ENABLE_FORK_SUPPORT
  fork_support_enabled = 1;
#else
  fork_support_enabled = 0;
#endif
  char* env = gpr_getenv("GRPC_ENABLE_FORK_SUPPORT");
  if (env != nullptr) {
    static const char* truthy[] = {"yes",  "Yes",  "YES", "true",
                                   "True", "TRUE", "1"};
    static const char* falsey[] = {"no",    "No",    "NO", "false",
                                   "False", "FALSE", "0"};
    for (size_t i = 0; i < GPR_ARRAY_SIZE(truthy); i++) {
      if (0 == strcmp(env, truthy[i])) {
        fork_support_enabled = 1;
      }
    }
    for (size_t i = 0; i < GPR_ARRAY_SIZE(falsey); i++) {
      if (0 == strcmp(env, falsey[i])) {
        fork_support_enabled = 0;
      }
    }
    gpr_free(env);
  }
  if (override_fork_support_enabled != -1) {
    fork_support_enabled = override_fork_support_enabled;
  }
}

int grpc_fork_support_enabled() { return fork_support_enabled; }

void grpc_enable_fork_support(int enable) {
  override_fork_support_enabled = enable;
}
<|endoftext|>


<commit_before>// 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.

#ifndef __STOUT_WINDOWS_OS_HPP__
#define __STOUT_WINDOWS_OS_HPP__

#include <direct.h>
#include <io.h>

#include <sys/utime.h>

#include <list>
#include <map>
#include <set>
#include <string>

#include <stout/duration.hpp>
#include <stout/none.hpp>
#include <stout/nothing.hpp>
#include <stout/option.hpp>
#include <stout/path.hpp>
#include <stout/try.hpp>
#include <stout/windows.hpp>

#include <stout/os/os.hpp>
#include <stout/os/read.hpp>

#include <stout/os/raw/environment.hpp>

namespace os {

inline int pagesize()
{
  SYSTEM_INFO si = {0};
  GetSystemInfo(&si);
  return si.dwPageSize;
}

// Sets the value associated with the specified key in the set of
// environment variables.
inline void setenv(
    const std::string& key,
    const std::string& value,
    bool overwrite = true)
{
  // Do not set the variable if already set and `overwrite` was not specified.
  //
  // Per MSDN[1], `GetEnvironmentVariable` returns 0 on error and sets the
  // error code to `ERROR_ENVVAR_NOT_FOUND` if the variable was not found.
  //
  // [1] https://msdn.microsoft.com/en-us/library/windows/desktop/ms683188(v=vs.85).aspx
  if (!overwrite &&
      ::GetEnvironmentVariable(key.c_str(), NULL, 0) != 0 &&
      ::GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
    return;
  }

  // `SetEnvironmentVariable` returns an error code, but we can't act on it.
  ::SetEnvironmentVariable(key.c_str(), value.c_str());
}

/*
// Unsets the value associated with the specified key in the set of
// environment variables.
inline void unsetenv(const std::string& key)
{
  UNIMPLEMENTED;
}

// Executes a command by calling "/bin/sh -c <command>", and returns
// after the command has been completed. Returns 0 if succeeds, and
// return -1 on error (e.g., fork/exec/waitpid failed). This function
// is async signal safe. We return int instead of returning a Try
// because Try involves 'new', which is not async signal safe.
inline int system(const std::string& command)
{
  UNIMPLEMENTED;
}

// This function is a portable version of execvpe ('p' means searching
// executable from PATH and 'e' means setting environments). We add
// this function because it is not available on all systems.
//
// NOTE: This function is not thread safe. It is supposed to be used
// only after fork (when there is only one thread). This function is
// async signal safe.
inline int execvpe(const char* file, char** argv, char** envp)
{
  UNIMPLEMENTED;
}

inline Try<Nothing> chown(
    uid_t uid,
    gid_t gid,
    const std::string& path,
    bool recursive)
{
  UNIMPLEMENTED;
}

inline Try<Nothing> chmod(const std::string& path, int mode)
{
  UNIMPLEMENTED;
}

inline Try<Nothing> mknod(
    const std::string& path,
    mode_t mode,
    dev_t dev)
{
  UNIMPLEMENTED;
}

// Suspends execution for the given duration.
inline Try<Nothing> sleep(const Duration& duration)
{
  UNIMPLEMENTED;
}

// Returns the list of files that match the given (shell) pattern.
inline Try<std::list<std::string>> glob(const std::string& pattern)
{
  UNIMPLEMENTED;
}

// Returns the total number of cpus (cores).
inline Try<long> cpus()
{
  UNIMPLEMENTED;
}

// Returns load struct with average system loads for the last
// 1, 5 and 15 minutes respectively.
// Load values should be interpreted as usual average loads from
// uptime(1).
inline Try<Load> loadavg()
{
  UNIMPLEMENTED;
}

// Returns the total size of main and free memory.
inline Try<Memory> memory()
{
  UNIMPLEMENTED;
}

// Return the system information.
inline Try<UTSInfo> uname()
{
  UNIMPLEMENTED;
}

inline Try<std::list<Process>> processes()
{
  UNIMPLEMENTED;
}

// Overload of os::pids for filtering by groups and sessions.
// A group / session id of 0 will fitler on the group / session ID
// of the calling process.
inline Try<std::set<pid_t>> pids(Option<pid_t> group, Option<pid_t> session)
{
  UNIMPLEMENTED;
}
*/

inline tm* gmtime_r(const time_t* timep, tm* result)
{
  return ::gmtime_s(result, timep) == ERROR_SUCCESS ? result : NULL;
}

} // namespace os {

#endif // __STOUT_WINDOWS_OS_HPP__
<commit_msg>Stout: Uncommented functions and marked them as `= delete` instead.<commit_after>// 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.

#ifndef __STOUT_WINDOWS_OS_HPP__
#define __STOUT_WINDOWS_OS_HPP__

#include <direct.h>
#include <io.h>

#include <sys/utime.h>

#include <list>
#include <map>
#include <set>
#include <string>

#include <stout/duration.hpp>
#include <stout/none.hpp>
#include <stout/nothing.hpp>
#include <stout/option.hpp>
#include <stout/path.hpp>
#include <stout/try.hpp>
#include <stout/windows.hpp>

#include <stout/os/os.hpp>
#include <stout/os/read.hpp>

#include <stout/os/raw/environment.hpp>

namespace os {

inline int pagesize()
{
  SYSTEM_INFO si = {0};
  GetSystemInfo(&si);
  return si.dwPageSize;
}

// Sets the value associated with the specified key in the set of
// environment variables.
inline void setenv(
    const std::string& key,
    const std::string& value,
    bool overwrite = true)
{
  // Do not set the variable if already set and `overwrite` was not specified.
  //
  // Per MSDN[1], `GetEnvironmentVariable` returns 0 on error and sets the
  // error code to `ERROR_ENVVAR_NOT_FOUND` if the variable was not found.
  //
  // [1] https://msdn.microsoft.com/en-us/library/windows/desktop/ms683188(v=vs.85).aspx
  if (!overwrite &&
      ::GetEnvironmentVariable(key.c_str(), NULL, 0) != 0 &&
      ::GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
    return;
  }

  // `SetEnvironmentVariable` returns an error code, but we can't act on it.
  ::SetEnvironmentVariable(key.c_str(), value.c_str());
}

// Unsets the value associated with the specified key in the set of
// environment variables.
inline void unsetenv(const std::string& key) = delete;

// Executes a command by calling "/bin/sh -c <command>", and returns
// after the command has been completed. Returns 0 if succeeds, and
// return -1 on error (e.g., fork/exec/waitpid failed). This function
// is async signal safe. We return int instead of returning a Try
// because Try involves 'new', which is not async signal safe.
inline int system(const std::string& command) = delete;

// This function is a portable version of execvpe ('p' means searching
// executable from PATH and 'e' means setting environments). We add
// this function because it is not available on all systems.
//
// NOTE: This function is not thread safe. It is supposed to be used
// only after fork (when there is only one thread). This function is
// async signal safe.
inline int execvpe(const char* file, char** argv, char** envp) = delete;

inline Try<Nothing> chown(
    uid_t uid,
    gid_t gid,
    const std::string& path,
    bool recursive) = delete;

inline Try<Nothing> chmod(const std::string& path, int mode) = delete;

inline Try<Nothing> mknod(
    const std::string& path,
    mode_t mode,
    dev_t dev) = delete;

// Suspends execution for the given duration.
inline Try<Nothing> sleep(const Duration& duration) = delete;

// Returns the list of files that match the given (shell) pattern.
inline Try<std::list<std::string>> glob(const std::string& pattern) = delete;

// Returns the total number of cpus (cores).
inline Try<long> cpus() = delete;

// Returns load struct with average system loads for the last
// 1, 5 and 15 minutes respectively.
// Load values should be interpreted as usual average loads from
// uptime(1).
inline Try<Load> loadavg() = delete;

// Returns the total size of main and free memory.
inline Try<Memory> memory() = delete;

// Return the system information.
inline Try<UTSInfo> uname() = delete;

inline Try<std::list<Process>> processes() = delete;

// Overload of os::pids for filtering by groups and sessions.
// A group / session id of 0 will fitler on the group / session ID
// of the calling process.
inline Try<std::set<pid_t>> pids(
    Option<pid_t> group,
    Option<pid_t> session) = delete;

inline tm* gmtime_r(const time_t* timep, tm* result)
{
  return ::gmtime_s(result, timep) == ERROR_SUCCESS ? result : NULL;
}

} // namespace os {

#endif // __STOUT_WINDOWS_OS_HPP__
<|endoftext|>