<commit_before>#ifndef VSMC_CORE_PARTICLE_HPP
#define VSMC_CORE_PARTICLE_HPP

#include <vsmc/internal/common.hpp>
#include <vsmc/internal/resampling.hpp>

namespace vsmc {

/// \brief Particle class representing the whole particle set
/// \ingroup Core
///
/// \tparam T Requirement:
/// \li Constructor compatible with
/// \code T(Particle<T>::size_type N) \endcode
/// \li member function copy method compatible with
/// \code copy(Particle<T>::size_type from, Particle<T>::size_type to) \endcode
template <typename T>
class Particle
{
    public :

    /// The type of the number of particles
    typedef VSMC_SIZE_TYPE size_type;

    /// The type of the particle values
    typedef T value_type;

#ifdef VSMC_USE_SEQUENTIAL_RNG
    /// The type of the sequential pseudo random number generator C++11 engine
    typedef VSMC_SEQRNG_TYPE rng_type;
#else
    /// The type of the Counter-based random number generator
    typedef VSMC_CBRNG_TYPE cbrng_type;

    /// The type of the Counter-based random number generator C++11 engine
    typedef rng::Engine<cbrng_type> rng_type;
#endif

    /// The integer type of the seed
    typedef rng_type::result_type seed_type;

    /// The type of the weight and log weight vectors
    typedef Eigen::VectorXd weight_type;

    /// \brief Construct a Particle object with a given number of particles
    ///
    /// \param N The number of particles
    /// \param seed The seed to the parallel RNG system
    ///
    /// \post All weights are initialized to be euqal to each other
    explicit Particle (size_type N, seed_type seed = VSMC_RNG_SEED) :
        size_(N), value_(N), ess_(N),
        weight_(N), log_weight_(N), inc_weight_(N), replication_(N),
        ess_cached_(false), weight_cached_(false), log_weight_cached_(false),
        resampled_(false), zconst_(0), seed_(seed)
#ifndef VSMC_USE_SEQUENTIAL_RNG
        , prng_(N)
#endif
    {
        reset_rng();
        set_equal_weight();
    }

    /// Size of the particle set
    size_type size () const
    {
        return size_;
    }

    /// Read and write access to particle values
    value_type &value ()
    {
        return value_;
    }

    /// Read only access to particle values
    const value_type &value () const
    {
        return value_;
    }

    /// Read only access to the weights
    const weight_type &weight () const
    {
        if (!weight_cached_) {
            weight_ = log_weight().array().exp();
            double sum = weight_.sum();
            weight_ *= 1 / sum;
            weight_cached_ = true;
        }

        return weight_;
    }

    /// Read only access to the log weights
    const weight_type &log_weight () const
    {
        if (!log_weight_cached_) {
            double max_weight = log_weight_.maxCoeff();
            log_weight_ = log_weight_.array() - max_weight;
            log_weight_cached_ = true;
        }

        return log_weight_;
    }

    /// Set equal weights for all particles
    void set_equal_weight ()
    {
        ess_ = size_;
        weight_.setConstant(1.0 / size_);
        log_weight_.setConstant(0);

        ess_cached_ = true;
        weight_cached_ = true;
        log_weight_cached_ = true;
    }

    /// \brief Set the log weights with a pointer
    ///
    /// \param new_weight The position to start the reading, it shall be valid
    /// after increments of size() times.
    /// \param delta A multiplier appiled to the new log weights
    void set_log_weight (const double *new_weight, double delta = 1)
    {
        Eigen::Map<const weight_type> w(new_weight, size_);
        set_log_weight(w, delta);
    }

    /// Set the log weights with a weight_type object
    void set_log_weight (const weight_type &new_weight, double delta = 1)
    {
        log_weight_ = delta * new_weight.head(size_);
        set_log_weight();
    }

    /// \brief Add to the log weights with a pointer
    ///
    /// \param inc_weight The position to start the reading, it shall be valid
    /// after increments of size() times.
    /// \param delta A multiplier appiled to the new incremental log weights
    /// \param add_zconst Whether this incremental weights shall contribute to
    /// the SMC normalizing constant estimate
    void add_log_weight (const double *inc_weight, double delta = 1,
            bool add_zconst = true)
    {
        Eigen::Map<const weight_type> w(inc_weight, size_);
        add_log_weight(w, delta, add_zconst);
    }

    /// Add to the log weights with a weight_object object
    void add_log_weight (const weight_type &inc_weight, double delta = 1,
            bool add_zconst = true)<commit_msg>Use DenseBase as input to weight mutators<commit_after>#ifndef VSMC_CORE_PARTICLE_HPP
#define VSMC_CORE_PARTICLE_HPP

#include <vsmc/internal/common.hpp>
#include <vsmc/internal/resampling.hpp>

namespace vsmc {

/// \brief Particle class representing the whole particle set
/// \ingroup Core
///
/// \tparam T Requirement:
/// \li Constructor compatible with
/// \code T(Particle<T>::size_type N) \endcode
/// \li member function copy method compatible with
/// \code copy(Particle<T>::size_type from, Particle<T>::size_type to) \endcode
template <typename T>
class Particle
{
    public :

    /// The type of the number of particles
    typedef VSMC_SIZE_TYPE size_type;

    /// The type of the particle values
    typedef T value_type;

#ifdef VSMC_USE_SEQUENTIAL_RNG
    /// The type of the sequential pseudo random number generator C++11 engine
    typedef VSMC_SEQRNG_TYPE rng_type;
#else
    /// The type of the Counter-based random number generator
    typedef VSMC_CBRNG_TYPE cbrng_type;

    /// The type of the Counter-based random number generator C++11 engine
    typedef rng::Engine<cbrng_type> rng_type;
#endif

    /// The integer type of the seed
    typedef rng_type::result_type seed_type;

    /// The type of the weight and log weight vectors
    typedef Eigen::VectorXd weight_type;

    /// \brief Construct a Particle object with a given number of particles
    ///
    /// \param N The number of particles
    /// \param seed The seed to the parallel RNG system
    ///
    /// \post All weights are initialized to be euqal to each other
    explicit Particle (size_type N, seed_type seed = VSMC_RNG_SEED) :
        size_(N), value_(N), ess_(N),
        weight_(N), log_weight_(N), inc_weight_(N), replication_(N),
        ess_cached_(false), weight_cached_(false), log_weight_cached_(false),
        resampled_(false), zconst_(0), seed_(seed)
#ifndef VSMC_USE_SEQUENTIAL_RNG
        , prng_(N)
#endif
    {
        reset_rng();
        set_equal_weight();
    }

    /// Size of the particle set
    size_type size () const
    {
        return size_;
    }

    /// Read and write access to particle values
    value_type &value ()
    {
        return value_;
    }

    /// Read only access to particle values
    const value_type &value () const
    {
        return value_;
    }

    /// Read only access to the weights
    const weight_type &weight () const
    {
        if (!weight_cached_) {
            weight_ = log_weight().array().exp();
            double sum = weight_.sum();
            weight_ *= 1 / sum;
            weight_cached_ = true;
        }

        return weight_;
    }

    /// Read only access to the log weights
    const weight_type &log_weight () const
    {
        if (!log_weight_cached_) {
            double max_weight = log_weight_.maxCoeff();
            log_weight_ = log_weight_.array() - max_weight;
            log_weight_cached_ = true;
        }

        return log_weight_;
    }

    /// Set equal weights for all particles
    void set_equal_weight ()
    {
        ess_ = size_;
        weight_.setConstant(1.0 / size_);
        log_weight_.setConstant(0);

        ess_cached_ = true;
        weight_cached_ = true;
        log_weight_cached_ = true;
    }

    /// \brief Set the log weights with a pointer
    ///
    /// \param new_weight The position to start the reading, it shall be valid
    /// after increments of size() times.
    /// \param delta A multiplier appiled to the new log weights
    void set_log_weight (const double *new_weight, double delta = 1)
    {
        Eigen::Map<const weight_type> w(new_weight, size_);
        set_log_weight(w, delta);
    }

    /// Set the log weights with a weight_type object
    template <typename Derived>
    void set_log_weight (const Eigen::DenseBase<Derived> &new_weight,
            double delta = 1)
    {
        log_weight_ = delta * new_weight.head(size_);
        set_log_weight();
    }

    /// \brief Add to the log weights with a pointer
    ///
    /// \param inc_weight The position to start the reading, it shall be valid
    /// after increments of size() times.
    /// \param delta A multiplier appiled to the new incremental log weights
    /// \param add_zconst Whether this incremental weights shall contribute to
    /// the SMC normalizing constant estimate
    void add_log_weight (const double *inc_weight, double delta = 1,
            bool add_zconst = true)
    {
        Eigen::Map<const weight_type> w(inc_weight, size_);
        add_log_weight(w, delta, add_zconst);
    }

    /// Add to the log weights with a weight_object object
    template <typename Derived>
    void add_log_weight (const Eigen::DenseBase<Derived> &inc_weight,
            double delta = 1, bool add_zconst = true)
{'fraction_non_alphanumeric': 0.09288453344695356, 'fraction_numerical': 0.0027694929697486153, 'mean_word_length': 2.4154237904692617, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '99813', 'n_tokens_mistral': 2812, 'n_tokens_neox': 2722, 'n_words': 915}