<commit_before>#ifndef MJOLNIR_UNLIMITED_GRID_CELL_LIST
#define MJOLNIR_UNLIMITED_GRID_CELL_LIST
#include <mjolnir/util/logger.hpp>
#include <functional>
#include <unordered_map>
#include <tuple>
#include <cmath>

namespace std
{

template<>
struct hash<std::tuple<int, int, int>>
{
    typedef std::tuple<int, int, int> argument_type;
    std::size_t operator()(argument_type const& val) const
    {
        const hash<int> h;
        return h(std::get<0>(val)) ^ h(std::get<1>(val)) ^ h(std::get<2>(val));
    }
};

} // std

namespace mjolnir
{

template<typename traitsT>
class UnlimitedGridCellList : public SpatialPartition<traitsT>
{
  public:

    typedef SpatialPartition<traitsT> base_type;
    typedef typename base_type::time_type time_type;
    typedef typename base_type::real_type real_type;
    typedef typename base_type::coordinate_type coordinate_type;
    typedef typename base_type::coordinate_type position_type;
    typedef typename base_type::particle_container_type particle_container_type;
    typedef typename base_type::index_type index_type;
    typedef typename base_type::index_list index_list;
    typedef std::tuple<int, int, int> cell_index_type;
    typedef std::vector<index_list> verlet_list_type;
    typedef std::vector<index_list> except_list_type;

  private:

    constexpr static real_type mesh_epsilon = 1e-6;
    typedef std::unordered_map<cell_index_type, index_list> cell_list_type;

  public:

    UnlimitedGridCellList() = default;
    ~UnlimitedGridCellList() override = default;

    UnlimitedGridCellList(const real_type cutoff, const real_type mergin)
        : dt_(0.), cutoff_(cutoff), mergin_(mergin), current_mergin_(-1.),
          inv_cell_size_(1. / (cutoff + mergin + mesh_epsilon))
    {}
    UnlimitedGridCellList(const real_type cutoff, const real_type mergin,
                          const time_type dt)
        : dt_(dt), cutoff_(cutoff), mergin_(mergin), current_mergin_(-1.),
          inv_cell_size_(1. / (cutoff + mergin + mesh_epsilon))
    {}

    bool valid() const noexcept override
    {
        return current_mergin_ >= 0. || dt_ == 0.;
    }

    void make  (const particle_container_type& pcon) override;
    void update(const particle_container_type& pcon) override;
    void update(const particle_container_type& pcon, const time_type dt) override;

    void add_except(const index_type i, const index_type j);
    void set_except(const except_list_type& ex){except_ = ex;}
    void set_except(except_list_type&& ex);

    real_type const& cutoff() const {return this->cutoff_;}
    real_type const& mergin() const {return this->mergin_;}

    void set_cutoff(const real_type c);
    void set_mergin(const real_type m);

    index_list const& partners(const std::size_t i) const override;
    index_list &      partners(const std::size_t i)       override;

  private:

    cell_index_type index(const position_type& pos) const;
    cell_index_type
    add(const int x, const int y, const int z, const cell_index_type&) const;

  private:

    real_type dt_;
    real_type cutoff_;
    real_type mergin_;
    real_type current_mergin_;
    real_type inv_cell_size_;

    verlet_list_type list_;
    except_list_type except_;

    cell_list_type   cell_list_;

    static Logger& logger_;
};

template<typename traitsT>
Logger& UnlimitedGridCellList<traitsT>::logger_ =
        LoggerManager<char>::get_logger("UnlimitedGridCellList");

template<typename traitsT>
inline void UnlimitedGridCellList<traitsT>::set_except(except_list_type&& ex)
{
    except_ = std::forward<except_list_type>(ex);
    return;
}

template<typename traitsT>
inline void UnlimitedGridCellList<traitsT>::set_cutoff(const real_type c)
{
    this->cutoff_ = c;
    this->inv_cell_size_ = 1. / (cutoff_ + mergin_ + mesh_epsilon);
    return;
}

template<typename traitsT>
inline void UnlimitedGridCellList<traitsT>::set_mergin(const real_type m)
{
    this->mergin_ = m;
    this->inv_cell_size_ = 1. / (cutoff_ + mergin_ + mesh_epsilon);
    return;
}

template<typename traitsT>
void UnlimitedGridCellList<traitsT>::make(const particle_container_type& pcon)
{
    MJOLNIR_LOG_DEBUG("UnlimitedGridCellList<traitsT>::make CALLED");

    list_.clear();
    list_.resize(pcon.size());
    cell_list_.clear();
    MJOLNIR_LOG_DEBUG("cell_list and verlet_list are cleared");

    const real_type r = cutoff_ + mergin_ + mesh_epsilon;
    MJOLNIR_LOG_DEBUG("unit cell size", r);
    MJOLNIR_LOG_DEBUG("inverse of it", inv_cell_size_);

    std::size_t idx = 0;
    for(auto iter = pcon.cbegin(); iter != pcon.cend(); ++iter)
    {
        const std::tuple<int, int, int> cell = index(iter->position);

        MJOLNIR_LOG_DEBUG(
                idx, "-th particle position", iter->position, "cell index",
                std::get<0>(cell), std::get<1>(cell), std::get<2>(cell));

        cell_list_[cell].push_back(idx);

        // adding its index to all the neighboring cells
        // to make the following code simple
        // (but of cource this consumes memory a lot.
        //  its a memory and performance matter)
        cell_list_[add( 1,  0,  0, cell)].push_back(idx);
        cell_list_[add( 0,  1,  0, cell)].push_back(idx);
        cell_list_[add( 0,  0,  1, cell)].push_back(idx);
        cell_list_[add(-1,  0,  0, cell)].push_back(idx);
        cell_list_[add( 0, -1,  0, cell)].push_back(idx);
        cell_list_[add( 0,  0, -1, cell)].push_back(idx);

        cell_list_[add( 1,  1,  0, cell)].push_back(idx);
        cell_list_[add( 0,  1,  1, cell)].push_back(idx);
        cell_list_[add( 1,  0,  1, cell)].push_back(idx);
        cell_list_[add(-1, -1,  0, cell)].push_back(idx);
        cell_list_[add( 0, -1, -1, cell)].push_back(idx);
        cell_list_[add(-1,  0, -1, cell)].push_back(idx);

        cell_list_[add( 1, -1,  0, cell)].push_back(idx);
        cell_list_[add( 0,  1, -1, cell)].push_back(idx);
        cell_list_[add(-1,  0,  1, cell)].push_back(idx);
        cell_list_[add(-1,  1,  0, cell)].push_back(idx);
        cell_list_[add( 0, -1,  1, cell)].push_back(idx);
        cell_list_[add( 1,  0, -1, cell)].push_back(idx);

        cell_list_[add(-1,  1,  1, cell)].push_back(idx);
        cell_list_[add( 1, -1,  1, cell)].push_back(idx);
        cell_list_[add( 1,  1, -1, cell)].push_back(idx);
        cell_list_[add(-1, -1,  1, cell)].push_back(idx);
        cell_list_[add( 1, -1, -1, cell)].push_back(idx);
        cell_list_[add(-1,  1, -1, cell)].push_back(idx);

        cell_list_[add( 1,  1,  1, cell)].push_back(idx);
        cell_list_[add(-1, -1, -1, cell)].push_back(idx);

        ++idx;
    }
    MJOLNIR_LOG_DEBUG("cell list is updated");

    const real_type r_c = cutoff_ + mergin_;
    const real_type r_c2 = r_c * r_c;

    MJOLNIR_LOG_DEBUG("except list size", except_.size());

    if(except_.empty())
    {
        MJOLNIR_LOG_DEBUG("exception list is empty. lookup all the particles");
        for(std::size_t i=0; i<pcon.size(); ++i)
        {
            const coordinate_type ri = pcon.at(i).position;
            const index_list& clist = cell_list_.at(index(ri));
            for(std::size_t j=0; j != clist.size(); ++j)
            {
                if(clist.at(j) == i) continue;
                const coordinate_type rij = pcon.at(clist.at(j)).position - ri;
                const real_type r2 = length_sq(rij);
                if(r2 < r_c2)
                    list_.at(i).push_back(j);
            }
        }
    }
    else
    {
        MJOLNIR_LOG_DEBUG("exception list is not empty.");
        MJOLNIR_LOG_DEBUG("lookup particles and also except list.");
        for(std::size_t i=0; i<pcon.size(); ++i)
        {
            const coordinate_type ri = pcon[i].position;
            const index_list& clist = cell_list_.at(index(ri));

            MJOLNIR_LOG_DEBUG("particle position", pcon[i].position);
            if(except_.at(i).empty())
            {
                MJOLNIR_LOG_DEBUG("except list for ", i, "-th value is empty.");
                for(std::size_t j=0; j != clist.size(); ++j)
                {
                    std::size_t k = clist.at(j);
                    if(k == i) continue;
                    const coordinate_type rij = pcon.at(k).position - ri;
                    const real_type r2 = length_sq(rij);
                    auto& verlet_list = list_.at(i);
                    if(r2 < r_c2 && i < k &&
                       std::find(verlet_list.cbegin(), verlet_list.cend(), k)
                           == verlet_list.cend())
                        verlet_list.push_back(k);
                }
            }
            else
            {
                MJOLNIR_LOG_DEBUG("making verlet list for index", i);
                MJOLNIR_LOG_DEBUG("except list for ", i, "-th value has",
                                  except_.at(i).size(), "particles");

                const auto cbeg = except_.at(i).cbegin();
                const auto cend = except_.at(i).cend();
                for(std::size_t j=0; j != clist.size(); ++j)
                {
                    MJOLNIR_LOG_DEBUG("looking", j, "-th particle in the cell.",
                                      "its index is", clist.at(j));

                    std::size_t k = clist.at(j);
                    if(k <= i || std::find(cbeg, cend, clist.at(j)) != cend)
                        continue;

                    const coordinate_type rij = pcon.at(k).position - ri;
                    const real_type r2 = length_sq(rij);
                    MJOLNIR_LOG_DEBUG("it is not in the except list.",
                                      " calculate distance^2", r2);

                    auto& verlet_list = list_.at(i);
                    if(r2 < r_c2)
                    {
                        MJOLNIR_LOG_DEBUG("add index", k, "to verlet list");
                        verlet_list.push_back(k);
                    }
                }
            }
        }
    }
    this->current_mergin_ = mergin_;

    MJOLNIR_LOG_DEBUG("UnlimitedGridCellList::make() RETURNED");
    return ;
}

template<typename traitsT>
inline typename UnlimitedGridCellList<traitsT>::cell_index_type
UnlimitedGridCellList<traitsT>::index(const position_type& pos) const
{
    return std::make_tuple(static_cast<int>(std::floor(pos[0]*inv_cell_size_)),
                           static_cast<int>(std::floor(pos[1]*inv_cell_size_)),
                           static_cast<int>(std::floor(pos[2]*inv_cell_size_)));
}

template<typename traitsT>
inline typename UnlimitedGridCellList<traitsT>::cell_index_type
UnlimitedGridCellList<traitsT>::add(
        const int x, const int y, const int z, const cell_index_type& idx) const
{
    return std::make_tuple(std::get<0>(idx) + x, std::get<1>(idx) + y,
                           std::get<2>(idx) + z);
}

template<typename traitsT>
void UnlimitedGridCellList<traitsT>::update(const particle_container_type& pcon)
{
    real_type max_speed = 0.;
    for(auto iter = pcon.cbegin(); iter != pcon.cend(); ++iter)
        max_speed = std::max(max_speed, length_sq(iter->velocity));

    this->current_mergin_ -= std::sqrt(max_speed) * dt_ * 2.;
    if(this->current_mergin_ < 0.)
        this->make(pcon);

    return ;
}

template<typename traitsT>
inline void UnlimitedGridCellList<traitsT>::update(
        const particle_container_type& pcon, const time_type dt)
{
    this->dt_ = dt;
    this->update(pcon);
    return ;
}

template<typename traitsT>
inline typename UnlimitedGridCellList<traitsT>::index_list const&
UnlimitedGridCellList<traitsT>::partners(const std::size_t i) const
{
    return list_.at(i);
}

template<typename traitsT>
inline typename UnlimitedGridCellList<traitsT>::index_list&
UnlimitedGridCellList<traitsT>::partners(const std::size_t i)
{
    return list_.at(i);
}

} // mjolnir
#endif/* MJOLNIR_UNLIMITED_GRID_CELL_LIST */
<commit_msg>remove std::hash object<commit_after>#ifndef MJOLNIR_UNLIMITED_GRID_CELL_LIST
#define MJOLNIR_UNLIMITED_GRID_CELL_LIST
#include <mjolnir/util/logger.hpp>
#include <functional>
#include <unordered_map>
#include <tuple>
#include <cmath>

namespace std
{

template<>
struct hash<std::tuple<int, int, int>>
{
    typedef std::tuple<int, int, int> argument_type;
    std::size_t operator()(argument_type const& val) const
    {
        return hash<int>()(std::get<0>(val)) ^
               hash<int>()(std::get<1>(val)) ^
               hash<int>()(std::get<2>(val));
    }
};

} // std

namespace mjolnir
{

template<typename traitsT>
class UnlimitedGridCellList : public SpatialPartition<traitsT>
{
  public:

    typedef SpatialPartition<traitsT> base_type;
    typedef typename base_type::time_type time_type;
    typedef typename base_type::real_type real_type;
    typedef typename base_type::coordinate_type coordinate_type;
    typedef typename base_type::coordinate_type position_type;
    typedef typename base_type::particle_container_type particle_container_type;
    typedef typename base_type::index_type index_type;
    typedef typename base_type::index_list index_list;
    typedef std::tuple<int, int, int> cell_index_type;
    typedef std::vector<index_list> verlet_list_type;
    typedef std::vector<index_list> except_list_type;

  private:

    constexpr static real_type mesh_epsilon = 1e-6;
    typedef std::unordered_map<cell_index_type, index_list> cell_list_type;

  public:

    UnlimitedGridCellList() = default;
    ~UnlimitedGridCellList() override = default;

    UnlimitedGridCellList(const real_type cutoff, const real_type mergin)
        : dt_(0.), cutoff_(cutoff), mergin_(mergin), current_mergin_(-1.),
          inv_cell_size_(1. / (cutoff + mergin + mesh_epsilon))
    {}
    UnlimitedGridCellList(const real_type cutoff, const real_type mergin,
                          const time_type dt)
        : dt_(dt), cutoff_(cutoff), mergin_(mergin), current_mergin_(-1.),
          inv_cell_size_(1. / (cutoff + mergin + mesh_epsilon))
    {}

    bool valid() const noexcept override
    {
        return current_mergin_ >= 0. || dt_ == 0.;
    }

    void make  (const particle_container_type& pcon) override;
    void update(const particle_container_type& pcon) override;
    void update(const particle_container_type& pcon, const time_type dt) override;

    void add_except(const index_type i, const index_type j);
    void set_except(const except_list_type& ex){except_ = ex;}
    void set_except(except_list_type&& ex);

    real_type const& cutoff() const {return this->cutoff_;}
    real_type const& mergin() const {return this->mergin_;}

    void set_cutoff(const real_type c);
    void set_mergin(const real_type m);

    index_list const& partners(const std::size_t i) const override;
    index_list &      partners(const std::size_t i)       override;

  private:

    cell_index_type index(const position_type& pos) const;
    cell_index_type
    add(const int x, const int y, const int z, const cell_index_type&) const;

  private:

    real_type dt_;
    real_type cutoff_;
    real_type mergin_;
    real_type current_mergin_;
    real_type inv_cell_size_;

    verlet_list_type list_;
    except_list_type except_;

    cell_list_type   cell_list_;

    static Logger& logger_;
};

template<typename traitsT>
Logger& UnlimitedGridCellList<traitsT>::logger_ =
        LoggerManager<char>::get_logger("UnlimitedGridCellList");

template<typename traitsT>
inline void UnlimitedGridCellList<traitsT>::set_except(except_list_type&& ex)
{
    except_ = std::forward<except_list_type>(ex);
    return;
}

template<typename traitsT>
inline void UnlimitedGridCellList<traitsT>::set_cutoff(const real_type c)
{
    this->cutoff_ = c;
    this->inv_cell_size_ = 1. / (cutoff_ + mergin_ + mesh_epsilon);
    return;
}

template<typename traitsT>
inline void UnlimitedGridCellList<traitsT>::set_mergin(const real_type m)
{
    this->mergin_ = m;
    this->inv_cell_size_ = 1. / (cutoff_ + mergin_ + mesh_epsilon);
    return;
}

template<typename traitsT>
void UnlimitedGridCellList<traitsT>::make(const particle_container_type& pcon)
{
    MJOLNIR_LOG_DEBUG("UnlimitedGridCellList<traitsT>::make CALLED");

    list_.clear();
    list_.resize(pcon.size());
    cell_list_.clear();
    MJOLNIR_LOG_DEBUG("cell_list and verlet_list are cleared");

    const real_type r = cutoff_ + mergin_ + mesh_epsilon;
    MJOLNIR_LOG_DEBUG("unit cell size", r);
    MJOLNIR_LOG_DEBUG("inverse of it", inv_cell_size_);

    std::size_t idx = 0;
    for(auto iter = pcon.cbegin(); iter != pcon.cend(); ++iter)
    {
        const std::tuple<int, int, int> cell = index(iter->position);

        MJOLNIR_LOG_DEBUG(
                idx, "-th particle position", iter->position, "cell index",
                std::get<0>(cell), std::get<1>(cell), std::get<2>(cell));

        cell_list_[cell].push_back(idx);

        // adding its index to all the neighboring cells
        // to make the following code simple
        // (but of cource this consumes memory a lot.
        //  its a memory and performance matter)
        cell_list_[add( 1,  0,  0, cell)].push_back(idx);
        cell_list_[add( 0,  1,  0, cell)].push_back(idx);
        cell_list_[add( 0,  0,  1, cell)].push_back(idx);
        cell_list_[add(-1,  0,  0, cell)].push_back(idx);
        cell_list_[add( 0, -1,  0, cell)].push_back(idx);
        cell_list_[add( 0,  0, -1, cell)].push_back(idx);

        cell_list_[add( 1,  1,  0, cell)].push_back(idx);
        cell_list_[add( 0,  1,  1, cell)].push_back(idx);
        cell_list_[add( 1,  0,  1, cell)].push_back(idx);
        cell_list_[add(-1, -1,  0, cell)].push_back(idx);
        cell_list_[add( 0, -1, -1, cell)].push_back(idx);
        cell_list_[add(-1,  0, -1, cell)].push_back(idx);

        cell_list_[add( 1, -1,  0, cell)].push_back(idx);
        cell_list_[add( 0,  1, -1, cell)].push_back(idx);
        cell_list_[add(-1,  0,  1, cell)].push_back(idx);
        cell_list_[add(-1,  1,  0, cell)].push_back(idx);
        cell_list_[add( 0, -1,  1, cell)].push_back(idx);
        cell_list_[add( 1,  0, -1, cell)].push_back(idx);

        cell_list_[add(-1,  1,  1, cell)].push_back(idx);
        cell_list_[add( 1, -1,  1, cell)].push_back(idx);
        cell_list_[add( 1,  1, -1, cell)].push_back(idx);
        cell_list_[add(-1, -1,  1, cell)].push_back(idx);
        cell_list_[add( 1, -1, -1, cell)].push_back(idx);
        cell_list_[add(-1,  1, -1, cell)].push_back(idx);

        cell_list_[add( 1,  1,  1, cell)].push_back(idx);
        cell_list_[add(-1, -1, -1, cell)].push_back(idx);

        ++idx;
    }
    MJOLNIR_LOG_DEBUG("cell list is updated");

    const real_type r_c = cutoff_ + mergin_;
    const real_type r_c2 = r_c * r_c;

    MJOLNIR_LOG_DEBUG("except list size", except_.size());

    if(except_.empty())
    {
        MJOLNIR_LOG_DEBUG("exception list is empty. lookup all the particles");
        for(std::size_t i=0; i<pcon.size(); ++i)
        {
            const coordinate_type ri = pcon.at(i).position;
            const index_list& clist = cell_list_.at(index(ri));
            for(std::size_t j=0; j != clist.size(); ++j)
            {
                if(clist.at(j) == i) continue;
                const coordinate_type rij = pcon.at(clist.at(j)).position - ri;
                const real_type r2 = length_sq(rij);
                if(r2 < r_c2)
                    list_.at(i).push_back(j);
            }
        }
    }
    else
    {
        MJOLNIR_LOG_DEBUG("exception list is not empty.");
        MJOLNIR_LOG_DEBUG("lookup particles and also except list.");
        for(std::size_t i=0; i<pcon.size(); ++i)
        {
            const coordinate_type ri = pcon[i].position;
            const index_list& clist = cell_list_.at(index(ri));

            MJOLNIR_LOG_DEBUG("particle position", pcon[i].position);
            if(except_.at(i).empty())
            {
                MJOLNIR_LOG_DEBUG("except list for ", i, "-th value is empty.");
                for(std::size_t j=0; j != clist.size(); ++j)
                {
                    std::size_t k = clist.at(j);
                    if(k == i) continue;
                    const coordinate_type rij = pcon.at(k).position - ri;
                    const real_type r2 = length_sq(rij);
                    auto& verlet_list = list_.at(i);
                    if(r2 < r_c2 && i < k &&
                       std::find(verlet_list.cbegin(), verlet_list.cend(), k)
                           == verlet_list.cend())
                        verlet_list.push_back(k);
                }
            }
            else
            {
                MJOLNIR_LOG_DEBUG("making verlet list for index", i);
                MJOLNIR_LOG_DEBUG("except list for ", i, "-th value has",
                                  except_.at(i).size(), "particles");

                const auto cbeg = except_.at(i).cbegin();
                const auto cend = except_.at(i).cend();
                for(std::size_t j=0; j != clist.size(); ++j)
                {
                    MJOLNIR_LOG_DEBUG("looking", j, "-th particle in the cell.",
                                      "its index is", clist.at(j));

                    std::size_t k = clist.at(j);
                    if(k <= i || std::find(cbeg, cend, clist.at(j)) != cend)
                        continue;

                    const coordinate_type rij = pcon.at(k).position - ri;
                    const real_type r2 = length_sq(rij);
                    MJOLNIR_LOG_DEBUG("it is not in the except list.",
                                      " calculate distance^2", r2);

                    auto& verlet_list = list_.at(i);
                    if(r2 < r_c2)
                    {
                        MJOLNIR_LOG_DEBUG("add index", k, "to verlet list");
                        verlet_list.push_back(k);
                    }
                }
            }
        }
    }
    this->current_mergin_ = mergin_;

    MJOLNIR_LOG_DEBUG("UnlimitedGridCellList::make() RETURNED");
    return ;
}

template<typename traitsT>
inline typename UnlimitedGridCellList<traitsT>::cell_index_type
UnlimitedGridCellList<traitsT>::index(const position_type& pos) const
{
    return std::make_tuple(static_cast<int>(std::floor(pos[0]*inv_cell_size_)),
                           static_cast<int>(std::floor(pos[1]*inv_cell_size_)),
                           static_cast<int>(std::floor(pos[2]*inv_cell_size_)));
}

template<typename traitsT>
inline typename UnlimitedGridCellList<traitsT>::cell_index_type
UnlimitedGridCellList<traitsT>::add(
        const int x, const int y, const int z, const cell_index_type& idx) const
{
    return std::make_tuple(std::get<0>(idx) + x, std::get<1>(idx) + y,
                           std::get<2>(idx) + z);
}

template<typename traitsT>
void UnlimitedGridCellList<traitsT>::update(const particle_container_type& pcon)
{
    real_type max_speed = 0.;
    for(auto iter = pcon.cbegin(); iter != pcon.cend(); ++iter)
        max_speed = std::max(max_speed, length_sq(iter->velocity));

    this->current_mergin_ -= std::sqrt(max_speed) * dt_ * 2.;
    if(this->current_mergin_ < 0.)
        this->make(pcon);

    return ;
}

template<typename traitsT>
inline void UnlimitedGridCellList<traitsT>::update(
        const particle_container_type& pcon, const time_type dt)
{
    this->dt_ = dt;
    this->update(pcon);
    return ;
}

template<typename traitsT>
inline typename UnlimitedGridCellList<traitsT>::index_list const&
UnlimitedGridCellList<traitsT>::partners(const std::size_t i) const
{
    return list_.at(i);
}

template<typename traitsT>
inline typename UnlimitedGridCellList<traitsT>::index_list&
UnlimitedGridCellList<traitsT>::partners(const std::size_t i)
{
    return list_.at(i);
}

} // mjolnir
#endif/* MJOLNIR_UNLIMITED_GRID_CELL_LIST */
<|endoftext|>


<commit_before>#include <igl/read_triangle_mesh.h>
#include <igl/write_triangle_mesh.h>
#include <string>
#include <iostream>
int main(int argc, char * argv[])
{
  using namespace std;
  using namespace Eigen;
  using namespace igl;
  MatrixXd V;
  MatrixXi F;
  string in,out;
  switch(argc)
  {
    case 3:
      in = argv[1];
      out = argv[2];
      break;
    default:
      cerr<<R"(
USAGE:
  convertmesh input.[mesh|obj|off|ply|stl|wrl] output.[mesh|obj|off|ply|stl|wrl]

  Note: .ply and .stl outputs are binary.
)";
    return EXIT_FAILURE;
  }
  return
    read_triangle_mesh(in,V,F) && write_triangle_mesh(out,V,F,false) ?
    EXIT_SUCCESS : EXIT_FAILURE;
}
<commit_msg>support for dae files<commit_after>#include <igl/read_triangle_mesh.h>
//#include <igl/write_triangle_mesh.h>
// Use igl::xml version to support .dae collada files, too
#include <igl/xml/write_triangle_mesh.h>
#include <string>
#include <iostream>
int main(int argc, char * argv[])
{
  using namespace std;
  using namespace Eigen;
  using namespace igl;
  MatrixXd V;
  MatrixXi F;
  string in,out;
  switch(argc)
  {
    case 3:
      in = argv[1];
      out = argv[2];
      break;
    default:
      cerr<<R"(
USAGE:
  convertmesh input.[mesh|obj|off|ply|stl|wrl] output.[mesh|obj|off|ply|stl|wrl]

  Note: .ply and .stl outputs are binary.
)";
    return EXIT_FAILURE;
  }
  return
    read_triangle_mesh(in,V,F) && xml::write_triangle_mesh(out,V,F,false) ?
    EXIT_SUCCESS : EXIT_FAILURE;
}
<|endoftext|>


<commit_before>//===- unittests/Lex/PreprocessingRecordTest.cpp - PreprocessingRecord tests =//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "clang/Basic/SourceManager.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/ModuleLoader.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/PreprocessingRecord.h"
#include "llvm/Config/config.h"

#include "gtest/gtest.h"

using namespace llvm;
using namespace clang;

namespace {

// The test fixture.
class PreprocessingRecordTest : public ::testing::Test {
protected:
  PreprocessingRecordTest()
    : FileMgr(FileMgrOpts),
      DiagID(new DiagnosticIDs()),
      Diags(DiagID, new IgnoringDiagConsumer()),
      SourceMgr(Diags, FileMgr),
      TargetOpts(new TargetOptions)
  {
    TargetOpts->Triple = "x86_64-apple-darwin11.1.0";
    Target = TargetInfo::CreateTargetInfo(Diags, *TargetOpts);
  }

  FileSystemOptions FileMgrOpts;
  FileManager FileMgr;
  IntrusiveRefCntPtr<DiagnosticIDs> DiagID;
  DiagnosticsEngine Diags;
  SourceManager SourceMgr;
  LangOptions LangOpts;
  IntrusiveRefCntPtr<TargetOptions> TargetOpts;
  IntrusiveRefCntPtr<TargetInfo> Target;
};

class VoidModuleLoader : public ModuleLoader {
  virtual Module *loadModule(SourceLocation ImportLoc, ModuleIdPath Path,
                             Module::NameVisibilityKind Visibility,
                             bool IsInclusionDirective) {
    return 0;
  }
};

TEST_F(PreprocessingRecordTest, PPRecAPI) {
  const char *source =
      "0 1\n"
      "#if 1\n"
      "2\n"
      "#ifndef BB\n"
      "3 4\n"
      "#else\n"
      "#endif\n"
      "5\n"
      "#endif\n"
      "6\n"
      "#if 1\n"
      "7\n"
      "#if 1\n"
      "#endif\n"
      "8\n"
      "#endif\n"
      "9\n";

  MemoryBuffer *buf = MemoryBuffer::getMemBuffer(source);
  SourceMgr.createMainFileIDForMemBuffer(buf);

  VoidModuleLoader ModLoader;
  HeaderSearch HeaderInfo(FileMgr, Diags, LangOpts, Target.getPtr());
  Preprocessor PP(Diags, LangOpts,
                  Target.getPtr(),
                  SourceMgr, HeaderInfo, ModLoader,
                  /*IILookup =*/ 0,
                  /*OwnsHeaderSearch =*/false,
                  /*DelayInitialization =*/ false);
  PP.createPreprocessingRecord(true);
  PP.EnterMainSourceFile();

  std::vector<Token> toks;
  while (1) {
    Token tok;
    PP.Lex(tok);
    if (tok.is(tok::eof))
      break;
    toks.push_back(tok);
  }

  // Make sure we got the tokens that we expected.
  ASSERT_EQ(10U, toks.size());

  PreprocessingRecord &PPRec = *PP.getPreprocessingRecord();
  EXPECT_FALSE(PPRec.rangeIntersectsConditionalDirective(
                    SourceRange(toks[0].getLocation(), toks[1].getLocation())));
  EXPECT_TRUE(PPRec.rangeIntersectsConditionalDirective(
                    SourceRange(toks[0].getLocation(), toks[2].getLocation())));
  EXPECT_FALSE(PPRec.rangeIntersectsConditionalDirective(
                    SourceRange(toks[3].getLocation(), toks[4].getLocation())));
  EXPECT_TRUE(PPRec.rangeIntersectsConditionalDirective(
                    SourceRange(toks[1].getLocation(), toks[5].getLocation())));
  EXPECT_TRUE(PPRec.rangeIntersectsConditionalDirective(
                    SourceRange(toks[2].getLocation(), toks[6].getLocation())));
  EXPECT_FALSE(PPRec.rangeIntersectsConditionalDirective(
                    SourceRange(toks[2].getLocation(), toks[5].getLocation())));
  EXPECT_FALSE(PPRec.rangeIntersectsConditionalDirective(
                    SourceRange(toks[0].getLocation(), toks[6].getLocation())));
  EXPECT_TRUE(PPRec.rangeIntersectsConditionalDirective(
                    SourceRange(toks[2].getLocation(), toks[8].getLocation())));
  EXPECT_FALSE(PPRec.rangeIntersectsConditionalDirective(
                    SourceRange(toks[0].getLocation(), toks[9].getLocation())));

  EXPECT_TRUE(PPRec.areInDifferentConditionalDirectiveRegion(
                    toks[0].getLocation(), toks[2].getLocation()));
  EXPECT_FALSE(PPRec.areInDifferentConditionalDirectiveRegion(
                    toks[3].getLocation(), toks[4].getLocation()));
  EXPECT_TRUE(PPRec.areInDifferentConditionalDirectiveRegion(
                    toks[1].getLocation(), toks[5].getLocation()));
  EXPECT_TRUE(PPRec.areInDifferentConditionalDirectiveRegion(
                    toks[2].getLocation(), toks[0].getLocation()));
  EXPECT_FALSE(PPRec.areInDifferentConditionalDirectiveRegion(
                    toks[4].getLocation(), toks[3].getLocation()));
  EXPECT_TRUE(PPRec.areInDifferentConditionalDirectiveRegion(
                    toks[5].getLocation(), toks[1].getLocation()));
}

} // anonymous namespace
<commit_msg>One last unit-test fix<commit_after>//===- unittests/Lex/PreprocessingRecordTest.cpp - PreprocessingRecord tests =//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "clang/Basic/SourceManager.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/ModuleLoader.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/PreprocessingRecord.h"
#include "llvm/Config/config.h"

#include "gtest/gtest.h"

using namespace llvm;
using namespace clang;

namespace {

// The test fixture.
class PreprocessingRecordTest : public ::testing::Test {
protected:
  PreprocessingRecordTest()
    : FileMgr(FileMgrOpts),
      DiagID(new DiagnosticIDs()),
      Diags(DiagID, new DiagnosticOptions, new IgnoringDiagConsumer()),
      SourceMgr(Diags, FileMgr),
      TargetOpts(new TargetOptions)
  {
    TargetOpts->Triple = "x86_64-apple-darwin11.1.0";
    Target = TargetInfo::CreateTargetInfo(Diags, *TargetOpts);
  }

  FileSystemOptions FileMgrOpts;
  FileManager FileMgr;
  IntrusiveRefCntPtr<DiagnosticIDs> DiagID;
  DiagnosticsEngine Diags;
  SourceManager SourceMgr;
  LangOptions LangOpts;
  IntrusiveRefCntPtr<TargetOptions> TargetOpts;
  IntrusiveRefCntPtr<TargetInfo> Target;
};

class VoidModuleLoader : public ModuleLoader {
  virtual Module *loadModule(SourceLocation ImportLoc, ModuleIdPath Path,
                             Module::NameVisibilityKind Visibility,
                             bool IsInclusionDirective) {
    return 0;
  }
};

TEST_F(PreprocessingRecordTest, PPRecAPI) {
  const char *source =
      "0 1\n"
      "#if 1\n"
      "2\n"
      "#ifndef BB\n"
      "3 4\n"
      "#else\n"
      "#endif\n"
      "5\n"
      "#endif\n"
      "6\n"
      "#if 1\n"
      "7\n"
      "#if 1\n"
      "#endif\n"
      "8\n"
      "#endif\n"
      "9\n";

  MemoryBuffer *buf = MemoryBuffer::getMemBuffer(source);
  SourceMgr.createMainFileIDForMemBuffer(buf);

  VoidModuleLoader ModLoader;
  HeaderSearch HeaderInfo(FileMgr, Diags, LangOpts, Target.getPtr());
  Preprocessor PP(Diags, LangOpts,
                  Target.getPtr(),
                  SourceMgr, HeaderInfo, ModLoader,
                  /*IILookup =*/ 0,
                  /*OwnsHeaderSearch =*/false,
                  /*DelayInitialization =*/ false);
  PP.createPreprocessingRecord(true);
  PP.EnterMainSourceFile();

  std::vector<Token> toks;
  while (1) {
    Token tok;
    PP.Lex(tok);
    if (tok.is(tok::eof))
      break;
    toks.push_back(tok);
  }

  // Make sure we got the tokens that we expected.
  ASSERT_EQ(10U, toks.size());

  PreprocessingRecord &PPRec = *PP.getPreprocessingRecord();
  EXPECT_FALSE(PPRec.rangeIntersectsConditionalDirective(
                    SourceRange(toks[0].getLocation(), toks[1].getLocation())));
  EXPECT_TRUE(PPRec.rangeIntersectsConditionalDirective(
                    SourceRange(toks[0].getLocation(), toks[2].getLocation())));
  EXPECT_FALSE(PPRec.rangeIntersectsConditionalDirective(
                    SourceRange(toks[3].getLocation(), toks[4].getLocation())));
  EXPECT_TRUE(PPRec.rangeIntersectsConditionalDirective(
                    SourceRange(toks[1].getLocation(), toks[5].getLocation())));
  EXPECT_TRUE(PPRec.rangeIntersectsConditionalDirective(
                    SourceRange(toks[2].getLocation(), toks[6].getLocation())));
  EXPECT_FALSE(PPRec.rangeIntersectsConditionalDirective(
                    SourceRange(toks[2].getLocation(), toks[5].getLocation())));
  EXPECT_FALSE(PPRec.rangeIntersectsConditionalDirective(
                    SourceRange(toks[0].getLocation(), toks[6].getLocation())));
  EXPECT_TRUE(PPRec.rangeIntersectsConditionalDirective(
                    SourceRange(toks[2].getLocation(), toks[8].getLocation())));
  EXPECT_FALSE(PPRec.rangeIntersectsConditionalDirective(
                    SourceRange(toks[0].getLocation(), toks[9].getLocation())));

  EXPECT_TRUE(PPRec.areInDifferentConditionalDirectiveRegion(
                    toks[0].getLocation(), toks[2].getLocation()));
  EXPECT_FALSE(PPRec.areInDifferentConditionalDirectiveRegion(
                    toks[3].getLocation(), toks[4].getLocation()));
  EXPECT_TRUE(PPRec.areInDifferentConditionalDirectiveRegion(
                    toks[1].getLocation(), toks[5].getLocation()));
  EXPECT_TRUE(PPRec.areInDifferentConditionalDirectiveRegion(
                    toks[2].getLocation(), toks[0].getLocation()));
  EXPECT_FALSE(PPRec.areInDifferentConditionalDirectiveRegion(
                    toks[4].getLocation(), toks[3].getLocation()));
  EXPECT_TRUE(PPRec.areInDifferentConditionalDirectiveRegion(
                    toks[5].getLocation(), toks[1].getLocation()));
}

} // anonymous namespace
<|endoftext|>


<commit_before>// Copyright (c) 2017-2019 The Dash Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <evo/cbtx.h>
#include <core_io.h>
#include <evo/deterministicmns.h>
#include <llmq/quorums.h>
#include <llmq/quorums_blockprocessor.h>
#include <llmq/quorums_commitment.h>
#include <evo/simplifiedmns.h>
#include <evo/specialtx.h>

#include <base58.h>
#include <chainparams.h>
#include <consensus/merkle.h>
#include <univalue.h>
#include <validation.h>

CSimplifiedMNListEntry::CSimplifiedMNListEntry(const CDeterministicMN& dmn) :
    proRegTxHash(dmn.proTxHash),
    confirmedHash(dmn.pdmnState->confirmedHash),
    service(dmn.pdmnState->addr),
    pubKeyOperator(dmn.pdmnState->pubKeyOperator),
    keyIDVoting(dmn.pdmnState->keyIDVoting),
    isValid(!dmn.pdmnState->IsBanned())
{
}

uint256 CSimplifiedMNListEntry::CalcHash() const
{
    CHashWriter hw(SER_GETHASH, CLIENT_VERSION);
    hw << *this;
    return hw.GetHash();
}

std::string CSimplifiedMNListEntry::ToString() const
{
    return strprintf("CSimplifiedMNListEntry(proRegTxHash=%s, confirmedHash=%s, service=%s, pubKeyOperator=%s, votingAddress=%s, isValid=%d)",
        proRegTxHash.ToString(), confirmedHash.ToString(), service.ToString(), pubKeyOperator.Get().ToString(), EncodeDestination(WitnessV0KeyHash(keyIDVoting)), isValid);
}

void CSimplifiedMNListEntry::ToJson(UniValue& obj) const
{
    obj.clear();
    obj.setObject();
    obj.pushKV("proRegTxHash", proRegTxHash.ToString());
    obj.pushKV("confirmedHash", confirmedHash.ToString());
    obj.pushKV("service", service.ToString());
    obj.pushKV("pubKeyOperator", pubKeyOperator.Get().ToString());
    obj.pushKV("votingAddress", EncodeDestination(WitnessV0KeyHash(keyIDVoting)));
    obj.pushKV("isValid", isValid);
}

CSimplifiedMNList::CSimplifiedMNList(const std::vector<CSimplifiedMNListEntry>& smlEntries)
{
    mnList.resize(smlEntries.size());
    for (size_t i = 0; i < smlEntries.size(); i++) {
        mnList[i] = std::make_unique<CSimplifiedMNListEntry>(smlEntries[i]);
    }

    std::sort(mnList.begin(), mnList.end(), [&](const std::unique_ptr<CSimplifiedMNListEntry>& a, const std::unique_ptr<CSimplifiedMNListEntry>& b) {
        return a->proRegTxHash.Compare(b->proRegTxHash) < 0;
    });
}

CSimplifiedMNList::CSimplifiedMNList(const CDeterministicMNList& dmnList)
{
    mnList.resize(dmnList.GetAllMNsCount());

    size_t i = 0;
    dmnList.ForEachMN(false, [this, &i](const CDeterministicMNCPtr& dmn) {
        mnList[i++] = std::make_unique<CSimplifiedMNListEntry>(*dmn);
    });

    std::sort(mnList.begin(), mnList.end(), [&](const std::unique_ptr<CSimplifiedMNListEntry>& a, const std::unique_ptr<CSimplifiedMNListEntry>& b) {
        return a->proRegTxHash.Compare(b->proRegTxHash) < 0;
    });
}

uint256 CSimplifiedMNList::CalcMerkleRoot(bool* pmutated) const
{
    std::vector<uint256> leaves;
    leaves.reserve(mnList.size());
    for (const auto& e : mnList) {
        leaves.emplace_back(e->CalcHash());
    }
    return ComputeMerkleRoot(leaves, pmutated);
}

CSimplifiedMNListDiff::CSimplifiedMNListDiff()
{
}

CSimplifiedMNListDiff::~CSimplifiedMNListDiff()
{
}

bool CSimplifiedMNListDiff::BuildQuorumsDiff(const CBlockIndex* baseBlockIndex, const CBlockIndex* blockIndex)
{
    auto baseQuorums = llmq::quorumBlockProcessor->GetMinedAndActiveCommitmentsUntilBlock(baseBlockIndex);
    auto quorums = llmq::quorumBlockProcessor->GetMinedAndActiveCommitmentsUntilBlock(blockIndex);

    std::set<std::pair<uint8_t, uint256>> baseQuorumHashes;
    std::set<std::pair<uint8_t, uint256>> quorumHashes;
    for (auto& p : baseQuorums) {
        for (auto& p2 : p.second) {
            baseQuorumHashes.emplace(p.first, p2->GetBlockHash());
        }
    }
    for (auto& p : quorums) {
        for (auto& p2 : p.second) {
            quorumHashes.emplace(p.first, p2->GetBlockHash());
        }
    }

    for (auto& p : baseQuorumHashes) {
        if (!quorumHashes.count(p)) {
            deletedQuorums.emplace_back(p.first, p.second);
        }
    }
    for (auto& p : quorumHashes) {
        if (!baseQuorumHashes.count(p)) {
            llmq::CFinalCommitment qc;
            uint256 minedBlockHash;
            if (!llmq::quorumBlockProcessor->GetMinedCommitment(p.first, p.second, qc, minedBlockHash)) {
                return false;
            }
            newQuorums.emplace_back(qc);
        }
    }
    return true;
}

void CSimplifiedMNListDiff::ToJson(UniValue& obj) const
{
    obj.setObject();

    obj.pushKV("baseBlockHash", baseBlockHash.ToString());
    obj.pushKV("blockHash", blockHash.ToString());

    CDataStream ssCbTxMerkleTree(SER_NETWORK, PROTOCOL_VERSION);
    ssCbTxMerkleTree << cbTxMerkleTree;
    obj.pushKV("cbTxMerkleTree", HexStr(ssCbTxMerkleTree.begin(), ssCbTxMerkleTree.end()));

    UniValue deletedMNsArr(UniValue::VARR);
    for (const auto& h : deletedMNs) {
        deletedMNsArr.push_back(h.ToString());
    }
    obj.pushKV("deletedMNs", deletedMNsArr);

    UniValue mnListArr(UniValue::VARR);
    for (const auto& e : mnList) {
        UniValue eObj;
        e.ToJson(eObj);
        mnListArr.push_back(eObj);
    }
    obj.pushKV("mnList", mnListArr);

    UniValue deletedQuorumsArr(UniValue::VARR);
    for (const auto& e : deletedQuorums) {
        UniValue eObj(UniValue::VOBJ);
        eObj.pushKV("llmqType", e.first);
        eObj.pushKV("quorumHash", e.second.ToString());
        deletedQuorumsArr.push_back(eObj);
    }
    obj.pushKV("deletedQuorums", deletedQuorumsArr);

    UniValue newQuorumsArr(UniValue::VARR);
    for (const auto& e : newQuorums) {
        UniValue eObj;
        e.ToJson(eObj);
        newQuorumsArr.push_back(eObj);
    }
    obj.pushKV("newQuorums", newQuorumsArr);
    obj.pushKV("merkleRootMNList", merkleRootMNList.ToString());
    obj.pushKV("merkleRootQuorums", merkleRootQuorums.ToString());
}

bool BuildSimplifiedMNListDiff(const uint256& baseBlockHash, const uint256& blockHash, CSimplifiedMNListDiff& mnListDiffRet, std::string& errorRet)
{
    AssertLockHeld(cs_main);
    mnListDiffRet = CSimplifiedMNListDiff();
    const CBlockIndex* baseBlockIndex = ::ChainActive().Genesis();
    if (!baseBlockHash.IsNull()) {
        baseBlockIndex = LookupBlockIndex(baseBlockHash);
        if (!baseBlockIndex) {
            errorRet = strprintf("block %s not found", baseBlockHash.ToString());
            return false;
        }
    }
    const CBlockIndex* blockIndex = LookupBlockIndex(blockHash);
    if (!blockIndex) {
        errorRet = strprintf("block %s not found", blockHash.ToString());
        return false;
    }
    if (!::ChainActive().Contains(baseBlockIndex) || !::ChainActive().Contains(blockIndex)) {
        errorRet = strprintf("block %s and %s are not in the same chain", baseBlockHash.ToString(), blockHash.ToString());
        return false;
    }
    if (baseBlockIndex->nHeight > blockIndex->nHeight) {
        errorRet = strprintf("base block %s is higher then block %s", baseBlockHash.ToString(), blockHash.ToString());
        return false;
    }
    LOCK(deterministicMNManager->cs);

    auto baseDmnList = deterministicMNManager->GetListForBlock(baseBlockIndex);
    auto dmnList = deterministicMNManager->GetListForBlock(blockIndex);
    mnListDiffRet = baseDmnList.BuildSimplifiedDiff(dmnList);
    // We need to return the value that was provided by the other peer as it otherwise won't be able to recognize the
    // response. This will usually be identical to the block found in baseBlockIndex. The only difference is when a
    // null block hash was provided to get the diff from the genesis block.
    mnListDiffRet.baseBlockHash = baseBlockHash;

    if (!mnListDiffRet.BuildQuorumsDiff(baseBlockIndex, blockIndex)) {
        errorRet = strprintf("failed to build quorums diff");
        return false;
    }
    // TODO store coinbase TX in CBlockIndex
    CBlock block;
    if (!ReadBlockFromDisk(block, blockIndex, Params().GetConsensus())) {
        errorRet = strprintf("failed to read block %s from disk", blockHash.ToString());
        return false;
    }
    CCbTx cbTxPayload;
    if(GetTxPayload(*block.vtx[0], cbTxPayload)) {
        mnListDiffRet.merkleRootMNList = cbTxPayload.merkleRootMNList;
        mnListDiffRet.merkleRootQuorums = cbTxPayload.merkleRootQuorums;
    } else {
        mnListDiffRet.merkleRootMNList.SetNull();
        mnListDiffRet.merkleRootQuorums.SetNull();
    }

    std::vector<uint256> vHashes;
    std::vector<bool> vMatch(block.vtx.size(), false);
    for (const auto& tx : block.vtx) {
        vHashes.emplace_back(tx->GetHash());
    }
    vMatch[0] = true; // only coinbase matches
    mnListDiffRet.cbTxMerkleTree = CPartialMerkleTree(vHashes, vMatch);
    return true;
}
<commit_msg>compile<commit_after>// Copyright (c) 2017-2019 The Dash Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <evo/cbtx.h>
#include <core_io.h>
#include <evo/deterministicmns.h>
#include <llmq/quorums.h>
#include <llmq/quorums_blockprocessor.h>
#include <llmq/quorums_commitment.h>
#include <evo/simplifiedmns.h>
#include <evo/specialtx.h>

#include <base58.h>
#include <chainparams.h>
#include <consensus/merkle.h>
#include <univalue.h>
#include <validation.h>

CSimplifiedMNListEntry::CSimplifiedMNListEntry(const CDeterministicMN& dmn) :
    proRegTxHash(dmn.proTxHash),
    confirmedHash(dmn.pdmnState->confirmedHash),
    service(dmn.pdmnState->addr),
    pubKeyOperator(dmn.pdmnState->pubKeyOperator),
    keyIDVoting(dmn.pdmnState->keyIDVoting),
    isValid(!dmn.pdmnState->IsBanned())
{
}

uint256 CSimplifiedMNListEntry::CalcHash() const
{
    CHashWriter hw(SER_GETHASH, CLIENT_VERSION);
    hw << *this;
    return hw.GetHash();
}

std::string CSimplifiedMNListEntry::ToString() const
{
    return strprintf("CSimplifiedMNListEntry(proRegTxHash=%s, confirmedHash=%s, service=%s, pubKeyOperator=%s, votingAddress=%s, isValid=%d)",
        proRegTxHash.ToString(), confirmedHash.ToString(), service.ToString(), pubKeyOperator.Get().ToString(), EncodeDestination(WitnessV0KeyHash(keyIDVoting)), isValid);
}

void CSimplifiedMNListEntry::ToJson(UniValue& obj) const
{
    obj.clear();
    obj.setObject();
    obj.pushKV("proRegTxHash", proRegTxHash.ToString());
    obj.pushKV("confirmedHash", confirmedHash.ToString());
    obj.pushKV("service", service.ToString());
    obj.pushKV("pubKeyOperator", pubKeyOperator.Get().ToString());
    obj.pushKV("votingAddress", EncodeDestination(WitnessV0KeyHash(keyIDVoting)));
    obj.pushKV("isValid", isValid);
}

CSimplifiedMNList::CSimplifiedMNList(const std::vector<CSimplifiedMNListEntry>& smlEntries)
{
    mnList.resize(smlEntries.size());
    for (size_t i = 0; i < smlEntries.size(); i++) {
        mnList[i] = std::make_unique<CSimplifiedMNListEntry>(smlEntries[i]);
    }

    std::sort(mnList.begin(), mnList.end(), [&](const std::unique_ptr<CSimplifiedMNListEntry>& a, const std::unique_ptr<CSimplifiedMNListEntry>& b) {
        return a->proRegTxHash.Compare(b->proRegTxHash) < 0;
    });
}

CSimplifiedMNList::CSimplifiedMNList(const CDeterministicMNList& dmnList)
{
    mnList.resize(dmnList.GetAllMNsCount());

    size_t i = 0;
    dmnList.ForEachMN(false, [this, &i](const CDeterministicMNCPtr& dmn) {
        mnList[i++] = std::make_unique<CSimplifiedMNListEntry>(*dmn);
    });

    std::sort(mnList.begin(), mnList.end(), [&](const std::unique_ptr<CSimplifiedMNListEntry>& a, const std::unique_ptr<CSimplifiedMNListEntry>& b) {
        return a->proRegTxHash.Compare(b->proRegTxHash) < 0;
    });
}

uint256 CSimplifiedMNList::CalcMerkleRoot(bool* pmutated) const
{
    std::vector<uint256> leaves;
    leaves.reserve(mnList.size());
    for (const auto& e : mnList) {
        leaves.emplace_back(e->CalcHash());
    }
    return ComputeMerkleRoot(leaves, pmutated);
}

CSimplifiedMNListDiff::CSimplifiedMNListDiff()
{
}

CSimplifiedMNListDiff::~CSimplifiedMNListDiff()
{
}

bool CSimplifiedMNListDiff::BuildQuorumsDiff(const CBlockIndex* baseBlockIndex, const CBlockIndex* blockIndex)
{
    auto baseQuorums = llmq::quorumBlockProcessor->GetMinedAndActiveCommitmentsUntilBlock(baseBlockIndex);
    auto quorums = llmq::quorumBlockProcessor->GetMinedAndActiveCommitmentsUntilBlock(blockIndex);

    std::set<std::pair<uint8_t, uint256>> baseQuorumHashes;
    std::set<std::pair<uint8_t, uint256>> quorumHashes;
    for (auto& p : baseQuorums) {
        for (auto& p2 : p.second) {
            baseQuorumHashes.emplace(p.first, p2->GetBlockHash());
        }
    }
    for (auto& p : quorums) {
        for (auto& p2 : p.second) {
            quorumHashes.emplace(p.first, p2->GetBlockHash());
        }
    }

    for (auto& p : baseQuorumHashes) {
        if (!quorumHashes.count(p)) {
            deletedQuorums.emplace_back(p.first, p.second);
        }
    }
    for (auto& p : quorumHashes) {
        if (!baseQuorumHashes.count(p)) {
            llmq::CFinalCommitment qc;
            uint256 minedBlockHash;
            if (!llmq::quorumBlockProcessor->GetMinedCommitment(p.first, p.second, qc, minedBlockHash)) {
                return false;
            }
            newQuorums.emplace_back(qc);
        }
    }
    return true;
}

void CSimplifiedMNListDiff::ToJson(UniValue& obj) const
{
    obj.setObject();

    obj.pushKV("baseBlockHash", baseBlockHash.ToString());
    obj.pushKV("blockHash", blockHash.ToString());

    CDataStream ssCbTxMerkleTree(SER_NETWORK, PROTOCOL_VERSION);
    ssCbTxMerkleTree << cbTxMerkleTree;
    obj.pushKV("cbTxMerkleTree", HexStr(ssCbTxMerkleTree));

    UniValue deletedMNsArr(UniValue::VARR);
    for (const auto& h : deletedMNs) {
        deletedMNsArr.push_back(h.ToString());
    }
    obj.pushKV("deletedMNs", deletedMNsArr);

    UniValue mnListArr(UniValue::VARR);
    for (const auto& e : mnList) {
        UniValue eObj;
        e.ToJson(eObj);
        mnListArr.push_back(eObj);
    }
    obj.pushKV("mnList", mnListArr);

    UniValue deletedQuorumsArr(UniValue::VARR);
    for (const auto& e : deletedQuorums) {
        UniValue eObj(UniValue::VOBJ);
        eObj.pushKV("llmqType", e.first);
        eObj.pushKV("quorumHash", e.second.ToString());
        deletedQuorumsArr.push_back(eObj);
    }
    obj.pushKV("deletedQuorums", deletedQuorumsArr);

    UniValue newQuorumsArr(UniValue::VARR);
    for (const auto& e : newQuorums) {
        UniValue eObj;
        e.ToJson(eObj);
        newQuorumsArr.push_back(eObj);
    }
    obj.pushKV("newQuorums", newQuorumsArr);
    obj.pushKV("merkleRootMNList", merkleRootMNList.ToString());
    obj.pushKV("merkleRootQuorums", merkleRootQuorums.ToString());
}

bool BuildSimplifiedMNListDiff(const uint256& baseBlockHash, const uint256& blockHash, CSimplifiedMNListDiff& mnListDiffRet, std::string& errorRet)
{
    AssertLockHeld(cs_main);
    mnListDiffRet = CSimplifiedMNListDiff();
    const CBlockIndex* baseBlockIndex = ::ChainActive().Genesis();
    if (!baseBlockHash.IsNull()) {
        baseBlockIndex = LookupBlockIndex(baseBlockHash);
        if (!baseBlockIndex) {
            errorRet = strprintf("block %s not found", baseBlockHash.ToString());
            return false;
        }
    }
    const CBlockIndex* blockIndex = LookupBlockIndex(blockHash);
    if (!blockIndex) {
        errorRet = strprintf("block %s not found", blockHash.ToString());
        return false;
    }
    if (!::ChainActive().Contains(baseBlockIndex) || !::ChainActive().Contains(blockIndex)) {
        errorRet = strprintf("block %s and %s are not in the same chain", baseBlockHash.ToString(), blockHash.ToString());
        return false;
    }
    if (baseBlockIndex->nHeight > blockIndex->nHeight) {
        errorRet = strprintf("base block %s is higher then block %s", baseBlockHash.ToString(), blockHash.ToString());
        return false;
    }
    LOCK(deterministicMNManager->cs);

    auto baseDmnList = deterministicMNManager->GetListForBlock(baseBlockIndex);
    auto dmnList = deterministicMNManager->GetListForBlock(blockIndex);
    mnListDiffRet = baseDmnList.BuildSimplifiedDiff(dmnList);
    // We need to return the value that was provided by the other peer as it otherwise won't be able to recognize the
    // response. This will usually be identical to the block found in baseBlockIndex. The only difference is when a
    // null block hash was provided to get the diff from the genesis block.
    mnListDiffRet.baseBlockHash = baseBlockHash;

    if (!mnListDiffRet.BuildQuorumsDiff(baseBlockIndex, blockIndex)) {
        errorRet = strprintf("failed to build quorums diff");
        return false;
    }
    // TODO store coinbase TX in CBlockIndex
    CBlock block;
    if (!ReadBlockFromDisk(block, blockIndex, Params().GetConsensus())) {
        errorRet = strprintf("failed to read block %s from disk", blockHash.ToString());
        return false;
    }
    CCbTx cbTxPayload;
    if(GetTxPayload(*block.vtx[0], cbTxPayload)) {
        mnListDiffRet.merkleRootMNList = cbTxPayload.merkleRootMNList;
        mnListDiffRet.merkleRootQuorums = cbTxPayload.merkleRootQuorums;
    } else {
        mnListDiffRet.merkleRootMNList.SetNull();
        mnListDiffRet.merkleRootQuorums.SetNull();
    }

    std::vector<uint256> vHashes;
    std::vector<bool> vMatch(block.vtx.size(), false);
    for (const auto& tx : block.vtx) {
        vHashes.emplace_back(tx->GetHash());
    }
    vMatch[0] = true; // only coinbase matches
    mnListDiffRet.cbTxMerkleTree = CPartialMerkleTree(vHashes, vMatch);
    return true;
}
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/message_center/message_center_bubble.h"

#include "grit/ui_strings.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/size.h"
#include "ui/message_center/message_view.h"
#include "ui/message_center/message_view_factory.h"
#include "ui/views/controls/button/text_button.h"
#include "ui/views/controls/label.h"
#include "ui/views/controls/scroll_view.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/layout/grid_layout.h"
#include "ui/views/painter.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"

namespace message_center {

namespace {

const int kMessageBubbleBaseMinHeight = 80;
const int kMessageBubbleBaseMaxHeight = 400;
const SkColor kBorderDarkColor = SkColorSetRGB(0xaa, 0xaa, 0xaa);

// The view for the buttons at the bottom of the web notification tray.
class WebNotificationButtonView : public views::View,
                                  public views::ButtonListener {
 public:
  explicit WebNotificationButtonView(NotificationList::Delegate* list_delegate)
      : list_delegate_(list_delegate),
        close_all_button_(NULL) {
    set_background(views::Background::CreateBackgroundPainter(
        true,
        views::Painter::CreateVerticalGradient(
            MessageBubbleBase::kHeaderBackgroundColorLight,
            MessageBubbleBase::kHeaderBackgroundColorDark)));
    set_border(views::Border::CreateSolidSidedBorder(
        2, 0, 0, 0, kBorderDarkColor));

    views::GridLayout* layout = new views::GridLayout(this);
    SetLayoutManager(layout);
    views::ColumnSet* columns = layout->AddColumnSet(0);
    columns->AddPaddingColumn(100, 0);
    columns->AddColumn(views::GridLayout::TRAILING, views::GridLayout::CENTER,
                       0, /* resize percent */
                       views::GridLayout::USE_PREF, 0, 0);
    columns->AddPaddingColumn(0, 4);

    ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
    close_all_button_ = new views::TextButton(
        this, rb.GetLocalizedString(IDS_MESSAGE_CENTER_CLEAR_ALL));
    close_all_button_->set_alignment(views::TextButton::ALIGN_CENTER);
    close_all_button_->set_focusable(true);
    close_all_button_->set_request_focus_on_press(false);

    layout->AddPaddingRow(0, 4);
    layout->StartRow(0, 0);
    layout->AddView(close_all_button_);
  }

  virtual ~WebNotificationButtonView() {}

  void SetCloseAllVisible(bool visible) {
    close_all_button_->SetVisible(visible);
  }

  // Overridden from ButtonListener.
  virtual void ButtonPressed(views::Button* sender,
                             const ui::Event& event) OVERRIDE {
    if (sender == close_all_button_)
      list_delegate_->SendRemoveAllNotifications();
  }

 private:
  NotificationList::Delegate* list_delegate_;
  views::TextButton* close_all_button_;

  DISALLOW_COPY_AND_ASSIGN(WebNotificationButtonView);
};

// A custom scroll-view that has a specified size.
class FixedSizedScrollView : public views::ScrollView {
 public:
  FixedSizedScrollView() {
    set_focusable(true);
    set_notify_enter_exit_on_child(true);
  }

  virtual ~FixedSizedScrollView() {}

  void SetFixedSize(const gfx::Size& size) {
    if (fixed_size_ == size)
      return;
    fixed_size_ = size;
    PreferredSizeChanged();
  }

  // views::View overrides.
  virtual gfx::Size GetPreferredSize() OVERRIDE {
    gfx::Size size = fixed_size_.IsEmpty() ?
        GetContents()->GetPreferredSize() : fixed_size_;
    gfx::Insets insets = GetInsets();
    size.Enlarge(insets.width(), insets.height());
    return size;
  }

  virtual void Layout() OVERRIDE {
    views::View* contents = GetContents();
    gfx::Rect bounds = gfx::Rect(contents->GetPreferredSize());
    bounds.set_width(std::max(0, width() - GetScrollBarWidth()));
    contents->SetBoundsRect(bounds);

    views::ScrollView::Layout();
    if (!vertical_scroll_bar()->visible()) {
      gfx::Rect bounds = contents->bounds();
      bounds.set_width(bounds.width() + GetScrollBarWidth());
      contents->SetBoundsRect(bounds);
    }
  }

  virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE {
    views::View* contents = GetContents();
    gfx::Rect bounds = gfx::Rect(contents->GetPreferredSize());
    bounds.set_width(std::max(0, width() - GetScrollBarWidth()));
    contents->SetBoundsRect(bounds);
  }

 private:
  gfx::Size fixed_size_;

  DISALLOW_COPY_AND_ASSIGN(FixedSizedScrollView);
};

// Container for the messages.
class ScrollContentView : public views::View {
 public:
  ScrollContentView() {
    views::BoxLayout* layout =
        new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1);
    layout->set_spread_blank_space(true);
    SetLayoutManager(layout);
  }

  virtual ~ScrollContentView() {
  }

  virtual gfx::Size GetPreferredSize() OVERRIDE {
    if (!preferred_size_.IsEmpty())
      return preferred_size_;
    return views::View::GetPreferredSize();
  }

  void set_preferred_size(const gfx::Size& size) { preferred_size_ = size; }

 private:
  gfx::Size preferred_size_;
  DISALLOW_COPY_AND_ASSIGN(ScrollContentView);
};

}  // namespace

// Message Center contents.
class MessageCenterContentsView : public views::View {
 public:
  explicit MessageCenterContentsView(NotificationList::Delegate* list_delegate)
      : list_delegate_(list_delegate) {
    SetLayoutManager(
        new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1));

    scroll_content_ = new ScrollContentView;
    scroller_ = new FixedSizedScrollView;
    scroller_->SetContents(scroll_content_);
    AddChildView(scroller_);

    scroller_->SetPaintToLayer(true);
    scroller_->SetFillsBoundsOpaquely(false);
    scroller_->layer()->SetMasksToBounds(true);

    button_view_ = new WebNotificationButtonView(list_delegate);
    AddChildView(button_view_);
  }

  void FocusContents() {
    scroller_->RequestFocus();
  }

  void Update(const NotificationList::Notifications& notifications)  {
    scroll_content_->RemoveAllChildViews(true);
    scroll_content_->set_preferred_size(gfx::Size());
    size_t num_children = 0;
    for (NotificationList::Notifications::const_iterator iter =
             notifications.begin(); iter != notifications.end(); ++iter) {
      MessageView* view =
          MessageViewFactory::ViewForNotification(*iter, list_delegate_);
      view->set_scroller(scroller_);
      view->SetUpView();
      scroll_content_->AddChildView(view);
      if (++num_children >=
          NotificationList::kMaxVisibleMessageCenterNotifications) {
        break;
      }
    }
    if (num_children == 0) {
      views::Label* label = new views::Label(l10n_util::GetStringUTF16(
          IDS_MESSAGE_CENTER_NO_MESSAGES));
      label->SetFont(label->font().DeriveFont(1));
      label->SetEnabledColor(SK_ColorGRAY);
      scroll_content_->AddChildView(label);
      button_view_->SetCloseAllVisible(false);
    } else {
      button_view_->SetCloseAllVisible(true);
    }
    SizeScrollContent();
    Layout();
    if (GetWidget())
      GetWidget()->GetRootView()->SchedulePaint();
  }

  size_t NumMessageViews() const {
    return scroll_content_->child_count();
  }

 private:
  void SizeScrollContent() {
    gfx::Size scroll_size = scroll_content_->GetPreferredSize();
    const int button_height = button_view_->GetPreferredSize().height();
    const int min_height = kMessageBubbleBaseMinHeight - button_height;
    const int max_height = kMessageBubbleBaseMaxHeight - button_height;
    int scroll_height = std::min(std::max(
        scroll_size.height(), min_height), max_height);
    scroll_size.set_height(scroll_height);
    if (scroll_height == min_height)
      scroll_content_->set_preferred_size(scroll_size);
    else
      scroll_content_->set_preferred_size(gfx::Size());
    scroller_->SetFixedSize(scroll_size);
    scroller_->SizeToPreferredSize();
    scroll_content_->InvalidateLayout();
  }

  NotificationList::Delegate* list_delegate_;
  FixedSizedScrollView* scroller_;
  ScrollContentView* scroll_content_;
  WebNotificationButtonView* button_view_;

  DISALLOW_COPY_AND_ASSIGN(MessageCenterContentsView);
};

// Message Center Bubble.
MessageCenterBubble::MessageCenterBubble(NotificationList::Delegate* delegate)
    : MessageBubbleBase(delegate),
      contents_view_(NULL) {
}

MessageCenterBubble::~MessageCenterBubble() {}

views::TrayBubbleView::InitParams MessageCenterBubble::GetInitParams(
    views::TrayBubbleView::AnchorAlignment anchor_alignment) {
  views::TrayBubbleView::InitParams init_params =
      GetDefaultInitParams(anchor_alignment);
  init_params.max_height = kMessageBubbleBaseMaxHeight;
  init_params.can_activate = true;
  return init_params;
}

void MessageCenterBubble::InitializeContents(
    views::TrayBubbleView* bubble_view) {
  bubble_view_ = bubble_view;
  contents_view_ = new MessageCenterContentsView(list_delegate_);
  bubble_view_->AddChildView(contents_view_);
  UpdateBubbleView();
  contents_view_->FocusContents();
}

void MessageCenterBubble::OnBubbleViewDestroyed() {
  contents_view_ = NULL;
}

void MessageCenterBubble::UpdateBubbleView() {
  if (!bubble_view_)
    return;  // Could get called after view is closed
  contents_view_->Update(
      list_delegate_->GetNotificationList()->notifications());
  bubble_view_->Show();
  bubble_view_->UpdateBubble();
}

void MessageCenterBubble::OnMouseEnteredView() {
}

void MessageCenterBubble::OnMouseExitedView() {
}

size_t MessageCenterBubble::NumMessageViewsForTest() const {
  return contents_view_->NumMessageViews();
}

}  // namespace message_center
<commit_msg>Changes the message item appearance in message center.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/message_center/message_center_bubble.h"

#include "grit/ui_strings.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/size.h"
#include "ui/message_center/message_view.h"
#include "ui/message_center/message_view_factory.h"
#include "ui/views/background.h"
#include "ui/views/border.h"
#include "ui/views/controls/button/text_button.h"
#include "ui/views/controls/label.h"
#include "ui/views/controls/scroll_view.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/layout/grid_layout.h"
#include "ui/views/painter.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"

namespace message_center {

namespace {

const int kMessageBubbleBaseMinHeight = 80;
const int kMessageBubbleBaseMaxHeight = 400;
const int kMarginBetweenItems = 10;
const SkColor kMessageCenterBackgroundColor = SkColorSetRGB(0xd3, 0xd3, 0xd3);
const SkColor kBorderDarkColor = SkColorSetRGB(0xaa, 0xaa, 0xaa);
const SkColor kMessageItemBorderWidth = 1;
const SkColor kMessageItemBorderColor = SkColorSetRGB(0xaa, 0xaa, 0xaa);

// The view for the buttons at the bottom of the web notification tray.
class WebNotificationButtonView : public views::View,
                                  public views::ButtonListener {
 public:
  explicit WebNotificationButtonView(NotificationList::Delegate* list_delegate)
      : list_delegate_(list_delegate),
        close_all_button_(NULL) {
    set_background(views::Background::CreateBackgroundPainter(
        true,
        views::Painter::CreateVerticalGradient(
            MessageBubbleBase::kHeaderBackgroundColorLight,
            MessageBubbleBase::kHeaderBackgroundColorDark)));
    set_border(views::Border::CreateSolidSidedBorder(
        2, 0, 0, 0, kBorderDarkColor));

    views::GridLayout* layout = new views::GridLayout(this);
    SetLayoutManager(layout);
    views::ColumnSet* columns = layout->AddColumnSet(0);
    columns->AddPaddingColumn(100, 0);
    columns->AddColumn(views::GridLayout::TRAILING, views::GridLayout::CENTER,
                       0, /* resize percent */
                       views::GridLayout::USE_PREF, 0, 0);
    columns->AddPaddingColumn(0, 4);

    ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
    close_all_button_ = new views::TextButton(
        this, rb.GetLocalizedString(IDS_MESSAGE_CENTER_CLEAR_ALL));
    close_all_button_->set_alignment(views::TextButton::ALIGN_CENTER);
    close_all_button_->set_focusable(true);
    close_all_button_->set_request_focus_on_press(false);

    layout->AddPaddingRow(0, 4);
    layout->StartRow(0, 0);
    layout->AddView(close_all_button_);
  }

  virtual ~WebNotificationButtonView() {}

  void SetCloseAllVisible(bool visible) {
    close_all_button_->SetVisible(visible);
  }

  // Overridden from ButtonListener.
  virtual void ButtonPressed(views::Button* sender,
                             const ui::Event& event) OVERRIDE {
    if (sender == close_all_button_)
      list_delegate_->SendRemoveAllNotifications();
  }

 private:
  NotificationList::Delegate* list_delegate_;
  views::TextButton* close_all_button_;

  DISALLOW_COPY_AND_ASSIGN(WebNotificationButtonView);
};

// A custom scroll-view that has a specified size.
class FixedSizedScrollView : public views::ScrollView {
 public:
  FixedSizedScrollView() {
    set_focusable(true);
    set_notify_enter_exit_on_child(true);
    set_background(views::Background::CreateSolidBackground(
        kMessageCenterBackgroundColor));
  }

  virtual ~FixedSizedScrollView() {}

  void SetFixedSize(const gfx::Size& size) {
    if (fixed_size_ == size)
      return;
    fixed_size_ = size;
    PreferredSizeChanged();
  }

  // views::View overrides.
  virtual gfx::Size GetPreferredSize() OVERRIDE {
    gfx::Size size = fixed_size_.IsEmpty() ?
        GetContents()->GetPreferredSize() : fixed_size_;
    gfx::Insets insets = GetInsets();
    size.Enlarge(insets.width(), insets.height());
    return size;
  }

  virtual void Layout() OVERRIDE {
    views::View* contents = GetContents();
    gfx::Rect bounds = gfx::Rect(contents->GetPreferredSize());
    bounds.set_width(std::max(0, width() - GetScrollBarWidth()));
    contents->SetBoundsRect(bounds);

    views::ScrollView::Layout();
    if (!vertical_scroll_bar()->visible()) {
      gfx::Rect bounds = contents->bounds();
      bounds.set_width(bounds.width() + GetScrollBarWidth());
      contents->SetBoundsRect(bounds);
    }
  }

  virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE {
    views::View* contents = GetContents();
    gfx::Rect bounds = gfx::Rect(contents->GetPreferredSize());
    bounds.set_width(std::max(0, width() - GetScrollBarWidth()));
    contents->SetBoundsRect(bounds);
  }

 private:
  gfx::Size fixed_size_;

  DISALLOW_COPY_AND_ASSIGN(FixedSizedScrollView);
};

// Container for the messages.
class ScrollContentView : public views::View {
 public:
  ScrollContentView() {
    SetLayoutManager(
        new views::BoxLayout(views::BoxLayout::kVertical,
                             kMarginBetweenItems,
                             kMarginBetweenItems,
                             kMarginBetweenItems));
    set_background(views::Background::CreateSolidBackground(
        kMessageCenterBackgroundColor));
  }

  virtual ~ScrollContentView() {
  }

  virtual gfx::Size GetPreferredSize() OVERRIDE {
    if (!preferred_size_.IsEmpty())
      return preferred_size_;
    return views::View::GetPreferredSize();
  }

  void set_preferred_size(const gfx::Size& size) { preferred_size_ = size; }

 private:
  gfx::Size preferred_size_;
  DISALLOW_COPY_AND_ASSIGN(ScrollContentView);
};

}  // namespace

// Message Center contents.
class MessageCenterContentsView : public views::View {
 public:
  explicit MessageCenterContentsView(NotificationList::Delegate* list_delegate)
      : list_delegate_(list_delegate) {
    SetLayoutManager(
        new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1));

    scroll_content_ = new ScrollContentView;
    scroller_ = new FixedSizedScrollView;
    scroller_->SetContents(scroll_content_);
    AddChildView(scroller_);

    scroller_->SetPaintToLayer(true);
    scroller_->SetFillsBoundsOpaquely(false);
    scroller_->layer()->SetMasksToBounds(true);

    button_view_ = new WebNotificationButtonView(list_delegate);
    AddChildView(button_view_);
  }

  void FocusContents() {
    scroller_->RequestFocus();
  }

  void Update(const NotificationList::Notifications& notifications)  {
    scroll_content_->RemoveAllChildViews(true);
    scroll_content_->set_preferred_size(gfx::Size());
    size_t num_children = 0;
    for (NotificationList::Notifications::const_iterator iter =
             notifications.begin(); iter != notifications.end(); ++iter) {
      MessageView* view =
          MessageViewFactory::ViewForNotification(*iter, list_delegate_);
      view->set_scroller(scroller_);
      view->set_border(views::Border::CreateSolidBorder(
          kMessageItemBorderWidth, kMessageItemBorderColor));
      view->SetUpView();
      scroll_content_->AddChildView(view);
      if (++num_children >=
          NotificationList::kMaxVisibleMessageCenterNotifications) {
        break;
      }
    }
    if (num_children == 0) {
      views::Label* label = new views::Label(l10n_util::GetStringUTF16(
          IDS_MESSAGE_CENTER_NO_MESSAGES));
      label->SetFont(label->font().DeriveFont(1));
      label->SetEnabledColor(SK_ColorGRAY);
      scroll_content_->AddChildView(label);
      button_view_->SetCloseAllVisible(false);
    } else {
      button_view_->SetCloseAllVisible(true);
    }
    SizeScrollContent();
    Layout();
    if (GetWidget())
      GetWidget()->GetRootView()->SchedulePaint();
  }

  size_t NumMessageViews() const {
    return scroll_content_->child_count();
  }

 private:
  void SizeScrollContent() {
    gfx::Size scroll_size = scroll_content_->GetPreferredSize();
    const int button_height = button_view_->GetPreferredSize().height();
    const int min_height = kMessageBubbleBaseMinHeight - button_height;
    const int max_height = kMessageBubbleBaseMaxHeight - button_height;
    int scroll_height = std::min(std::max(
        scroll_size.height(), min_height), max_height);
    scroll_size.set_height(scroll_height);
    if (scroll_height == min_height)
      scroll_content_->set_preferred_size(scroll_size);
    else
      scroll_content_->set_preferred_size(gfx::Size());
    scroller_->SetFixedSize(scroll_size);
    scroller_->SizeToPreferredSize();
    scroll_content_->InvalidateLayout();
  }

  NotificationList::Delegate* list_delegate_;
  FixedSizedScrollView* scroller_;
  ScrollContentView* scroll_content_;
  WebNotificationButtonView* button_view_;

  DISALLOW_COPY_AND_ASSIGN(MessageCenterContentsView);
};

// Message Center Bubble.
MessageCenterBubble::MessageCenterBubble(NotificationList::Delegate* delegate)
    : MessageBubbleBase(delegate),
      contents_view_(NULL) {
}

MessageCenterBubble::~MessageCenterBubble() {}

views::TrayBubbleView::InitParams MessageCenterBubble::GetInitParams(
    views::TrayBubbleView::AnchorAlignment anchor_alignment) {
  views::TrayBubbleView::InitParams init_params =
      GetDefaultInitParams(anchor_alignment);
  init_params.max_height = kMessageBubbleBaseMaxHeight;
  init_params.bubble_width += kMarginBetweenItems * 2;
  init_params.can_activate = true;
  return init_params;
}

void MessageCenterBubble::InitializeContents(
    views::TrayBubbleView* bubble_view) {
  bubble_view_ = bubble_view;
  contents_view_ = new MessageCenterContentsView(list_delegate_);
  bubble_view_->AddChildView(contents_view_);
  UpdateBubbleView();
  contents_view_->FocusContents();
}

void MessageCenterBubble::OnBubbleViewDestroyed() {
  contents_view_ = NULL;
}

void MessageCenterBubble::UpdateBubbleView() {
  if (!bubble_view_)
    return;  // Could get called after view is closed
  contents_view_->Update(
      list_delegate_->GetNotificationList()->notifications());
  bubble_view_->Show();
  bubble_view_->UpdateBubble();
}

void MessageCenterBubble::OnMouseEnteredView() {
}

void MessageCenterBubble::OnMouseExitedView() {
}

size_t MessageCenterBubble::NumMessageViewsForTest() const {
  return contents_view_->NumMessageViews();
}

}  // namespace message_center
<|endoftext|>


<commit_before>// Copyright 2010-2014 RethinkDB, all rights reserved.
#ifndef CONCURRENCY_PMAP_HPP_
#define CONCURRENCY_PMAP_HPP_

#include "arch/runtime/coroutines.hpp"
#include "concurrency/cond_var.hpp"
#include "concurrency/new_semaphore.hpp"

template <class callable_t, class value_t>
struct pmap_runner_one_arg_t {
    value_t i;
    const callable_t *c;
    int *outstanding;
    cond_t *to_signal;
    pmap_runner_one_arg_t(value_t _i, const callable_t *_c, int *_outstanding,
                          cond_t *_to_signal)
        : i(_i), c(_c), outstanding(_outstanding), to_signal(_to_signal) { }

    void operator()() {
        (*c)(i);
        (*outstanding)--;
        if (*outstanding == 0) {
            to_signal->pulse();
        }
    }
};

template <class callable_t, class value_t>
void spawn_pmap_runner_one_arg(value_t i, const callable_t *c, int *outstanding, cond_t *to_signal) {
    coro_t::spawn_now_dangerously(pmap_runner_one_arg_t<callable_t, value_t>(i, c, outstanding, to_signal));
}

template <class callable_t>
void pmap(int begin, int end, const callable_t &c) {
    guarantee(begin >= 0);  // We don't want `end - begin` to overflow, do we?
    guarantee(begin <= end);
    if (begin == end) {
        return;
    }

    cond_t cond;
    int outstanding = (end - begin);
    for (int i = begin; i < end - 1; ++i) {
        coro_t::spawn_now_dangerously(pmap_runner_one_arg_t<callable_t, int>(i, &c, &outstanding, &cond));
    }
    pmap_runner_one_arg_t<callable_t, int> runner(end - 1, &c, &outstanding, &cond);
    runner();
    cond.wait();
}

template <class callable_t>
void pmap(int count, const callable_t &c) {
    pmap(0, count, c);
}

template <class callable_t, class iterator_t>
void pmap(iterator_t start, iterator_t end, const callable_t &c) {
    cond_t cond;
    int outstanding = 1;
    while (start != end) {
        ++outstanding;
        spawn_pmap_runner_one_arg(*start, &c, &outstanding, &cond);
        ++start;
    }
    --outstanding;
    if (outstanding) {
        cond.wait();
    }
}

template <class callable_t, class value_t>
struct throttled_pmap_runner_t {
    value_t i;
    const callable_t *c;
    int *outstanding;
    cond_t *to_signal;
    new_semaphore_acq_t semaphore_acq;
    throttled_pmap_runner_t(value_t _i, const callable_t *_c, int *_outstanding,
                            cond_t *_to_signal, new_semaphore_acq_t &&acq)
        : i(_i), c(_c), outstanding(_outstanding), to_signal(_to_signal),
          semaphore_acq(std::move(acq)) { }

    void operator()() {
        (*c)(i);
        (*outstanding)--;
        semaphore_acq.reset();
        if (*outstanding == 0) {
            to_signal->pulse();
        }
    }
};

// TODO(2014-10): The types here are "int", but how do we know that won't overflow?
template <class callable_t>
void throttled_pmap(int begin, int end, const callable_t &c, int64_t capacity) {
    guarantee(capacity > 0);
    guarantee(begin >= 0);  // We don't want `end - begin` to overflow, do we?
    guarantee(begin <= end);
    if (begin == end) {
        return;
    }

    new_semaphore_t semaphore(capacity);
    cond_t cond;
    int outstanding = (end - begin);
    for (int i = begin; i < end - 1; ++i) {
        new_semaphore_acq_t acq(&semaphore, 1);
        acq.acquisition_signal()->wait();
        coro_t::spawn_now_dangerously(
            throttled_pmap_runner_t<callable_t, int>(i, &c, &outstanding, &cond,
                                                     std::move(acq)));
    }

    {
        new_semaphore_acq_t acq(&semaphore, 1);
        acq.acquisition_signal()->wait();
        throttled_pmap_runner_t<callable_t, int> runner(end - 1, &c, &outstanding,
                                                        &cond, std::move(acq));
        runner();
    }
    cond.wait();
}

template <class callable_t>
void throttled_pmap(int count, const callable_t &c, int64_t capacity) {
    throttled_pmap(0, count, c, capacity);
}

#endif /* CONCURRENCY_PMAP_HPP_ */
<commit_msg>Made pmap code use int64_t where it used int (semi-dangerously) before.<commit_after>// Copyright 2010-2014 RethinkDB, all rights reserved.
#ifndef CONCURRENCY_PMAP_HPP_
#define CONCURRENCY_PMAP_HPP_

#include "arch/runtime/coroutines.hpp"
#include "concurrency/cond_var.hpp"
#include "concurrency/new_semaphore.hpp"

template <class callable_t, class value_t>
struct pmap_runner_one_arg_t {
    value_t i;
    const callable_t *c;
    int64_t *outstanding;
    cond_t *to_signal;
    pmap_runner_one_arg_t(value_t _i, const callable_t *_c, int64_t *_outstanding,
                          cond_t *_to_signal)
        : i(_i), c(_c), outstanding(_outstanding), to_signal(_to_signal) { }

    void operator()() {
        (*c)(i);
        (*outstanding)--;
        if (*outstanding == 0) {
            to_signal->pulse();
        }
    }
};

template <class callable_t, class value_t>
void spawn_pmap_runner_one_arg(value_t i, const callable_t *c, int64_t *outstanding, cond_t *to_signal) {
    coro_t::spawn_now_dangerously(pmap_runner_one_arg_t<callable_t, value_t>(i, c, outstanding, to_signal));
}

template <class callable_t>
void pmap(int64_t begin, int64_t end, const callable_t &c) {
    guarantee(begin >= 0);  // We don't want `end - begin` to overflow, do we?
    guarantee(begin <= end);
    if (begin == end) {
        return;
    }

    cond_t cond;
    int64_t outstanding = (end - begin);
    for (int64_t i = begin; i < end - 1; ++i) {
        coro_t::spawn_now_dangerously(pmap_runner_one_arg_t<callable_t, int64_t>(i, &c, &outstanding, &cond));
    }
    pmap_runner_one_arg_t<callable_t, int64_t> runner(end - 1, &c, &outstanding, &cond);
    runner();
    cond.wait();
}

template <class callable_t>
void pmap(int64_t count, const callable_t &c) {
    pmap(0, count, c);
}

template <class callable_t, class iterator_t>
void pmap(iterator_t start, iterator_t end, const callable_t &c) {
    cond_t cond;
    int64_t outstanding = 1;
    while (start != end) {
        ++outstanding;
        spawn_pmap_runner_one_arg(*start, &c, &outstanding, &cond);
        ++start;
    }
    --outstanding;
    if (outstanding) {
        cond.wait();
    }
}

template <class callable_t, class value_t>
struct throttled_pmap_runner_t {
    value_t i;
    const callable_t *c;
    int64_t *outstanding;
    cond_t *to_signal;
    new_semaphore_acq_t semaphore_acq;
    throttled_pmap_runner_t(value_t _i, const callable_t *_c, int64_t *_outstanding,
                            cond_t *_to_signal, new_semaphore_acq_t &&acq)
        : i(_i), c(_c), outstanding(_outstanding), to_signal(_to_signal),
          semaphore_acq(std::move(acq)) { }

    void operator()() {
        (*c)(i);
        (*outstanding)--;
        semaphore_acq.reset();
        if (*outstanding == 0) {
            to_signal->pulse();
        }
    }
};

template <class callable_t>
void throttled_pmap(int64_t begin, int64_t end, const callable_t &c, int64_t capacity) {
    guarantee(capacity > 0);
    guarantee(begin >= 0);  // We don't want `end - begin` to overflow, do we?
    guarantee(begin <= end);
    if (begin == end) {
        return;
    }

    new_semaphore_t semaphore(capacity);
    cond_t cond;
    int64_t outstanding = (end - begin);
    for (int64_t i = begin; i < end - 1; ++i) {
        new_semaphore_acq_t acq(&semaphore, 1);
        acq.acquisition_signal()->wait();
        coro_t::spawn_now_dangerously(
            throttled_pmap_runner_t<callable_t, int64_t>(i, &c, &outstanding, &cond,
                                                         std::move(acq)));
    }

    {
        new_semaphore_acq_t acq(&semaphore, 1);
        acq.acquisition_signal()->wait();
        throttled_pmap_runner_t<callable_t, int64_t> runner(end - 1, &c, &outstanding,
                                                        &cond, std::move(acq));
        runner();
    }
    cond.wait();
}

template <class callable_t>
void throttled_pmap(int64_t count, const callable_t &c, int64_t capacity) {
    throttled_pmap(0, count, c, capacity);
}

#endif /* CONCURRENCY_PMAP_HPP_ */
<|endoftext|>


<commit_before>/**
 * \file tiles_search.cc
 *
 *
 *
 * \author Ethan Burns
 * \date 2008-11-11
 */

#include <assert.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#include <iostream>
#include <vector>

#include "get_search.h"
#include "search.h"
#include "state.h"
#include "h_zero.h"
#include "tiles/tiles.h"
#include "util/timer.h"
#include "util/timeout.h"
#include "sync_wastar.h"

using namespace std;

int main(int argc, char *argv[])
{
	// 90 seconds is too small to solve the 96 instance optimally in a consistent manner.
	unsigned int timelimit = 300;	// seconds
	vector<State *> *path;
	SyncWAStar *search;
	Tiles *g_orig = new Tiles(cin);
	Timer timer;

	Projection *project;
	if (nblocks == 0) {
		project = NULL;
	} else if (nblocks == 1 || nblocks == 240) {
		project = new Tiles::OneTileProject(g_orig);
	} else if (nblocks == 2 || nblocks == 3360) {
		project = new Tiles::TwoTileProject(g_orig);
	} else {
		cerr << "Invalid abstraction size: " << nblocks << endl;
		cerr << "15-puzzle: 240=1tile, 3360=2tile" << endl;
		exit(EXIT_FAILURE);
	}

	vector<double> *weights;
	vector<State *> *inits = new vector<State *>();
	unsigned int threads;
	bool dd;
	if (argc > 2
	    && sscanf(argv[1], "syncwastar-%u", &threads) == 1) {
		weights = parse_weights(argv[2]);
		dd = false;
	}else if (argc > 2
	    && sscanf(argv[1], "syncwastardd-%u", &threads) == 1) {
		weights = parse_weights(argv[2]);
		dd = true;
	}
	else{
		cerr << "bad input" << endl;
		exit(EXIT_FAILURE);
	}

	for(vector<double>::iterator i = weights->begin();
	    i != weights->end(); i++){
		Tiles *g = (Tiles*)malloc(sizeof(*g_orig));
		memcpy(g, g_orig, sizeof(*g_orig));
		g->set_projection(project);

		Tiles::ManhattanDist *manhattan = new Tiles::ManhattanDist(g);
		manhattan->set_weight(*i);
		g->set_heuristic(manhattan);
		inits->push_back(g->initial_state());
	}

	search = new SyncWAStar::SyncWAStar(threads, inits, dd);

#if defined(NDEBUG)
	timeout(timelimit);
#endif	// NDEBUG

	timer.start();
	path = search->search(&timer, NULL);
	timer.stop();

#if defined(NDEBUG)
	timeout_stop();
#endif	// NDEBUG

	search->output_stats();

	/* Print the graph to the terminal */
//	g.print(cout, path);

	if (path) {
		printf("cost: %f\n", (double) path->at(0)->get_g() / fp_one);
		cout << "length: " << path->size() << endl;

		// Make sure that the heuristic was actually admissible!
		for (unsigned int i = path->size() - 1; i >= 0; i -= 1) {
#if !defined(NDEBUG)
			State *s = path->at(i);
			fp_type togo = path->at(0)->get_g() - s->get_g();
			assert(s->get_h() <= togo);
#endif
			if (i > 0)
				assert(s->get_h() > 0);
			if (i == 0)
				break;
		}

		for (unsigned int i = 0; i < path->size(); i += 1)
			delete path->at(i);
		delete path;
	} else {
		cout << "# No Solution" << endl;
	}
	cout << "time-limit: " << timelimit << endl;
	cout << "wall_time: " << timer.get_wall_time() << endl;
	cout << "CPU_time: " << timer.get_processor_time() << endl;
	cout << "generated: " << search->get_generated() << endl;
	cout << "expanded: " << search->get_expanded() << endl;

	if (project)
		delete project;

	delete search;

	return EXIT_SUCCESS;
}
<commit_msg>Lower the timelimit on mulit wA* it eats up memory too quickly.<commit_after>/**
 * \file tiles_search.cc
 *
 *
 *
 * \author Ethan Burns
 * \date 2008-11-11
 */

#include <assert.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#include <iostream>
#include <vector>

#include "get_search.h"
#include "search.h"
#include "state.h"
#include "h_zero.h"
#include "tiles/tiles.h"
#include "util/timer.h"
#include "util/timeout.h"
#include "sync_wastar.h"

using namespace std;

int main(int argc, char *argv[])
{
	// 90 seconds is too small to solve the 96 instance optimally in a consistent manner.
	unsigned int timelimit = 120;	// seconds
	vector<State *> *path;
	SyncWAStar *search;
	Tiles *g_orig = new Tiles(cin);
	Timer timer;

	Projection *project;
	if (nblocks == 0) {
		project = NULL;
	} else if (nblocks == 1 || nblocks == 240) {
		project = new Tiles::OneTileProject(g_orig);
	} else if (nblocks == 2 || nblocks == 3360) {
		project = new Tiles::TwoTileProject(g_orig);
	} else {
		cerr << "Invalid abstraction size: " << nblocks << endl;
		cerr << "15-puzzle: 240=1tile, 3360=2tile" << endl;
		exit(EXIT_FAILURE);
	}

	vector<double> *weights;
	vector<State *> *inits = new vector<State *>();
	unsigned int threads;
	bool dd;
	if (argc > 2
	    && sscanf(argv[1], "syncwastar-%u", &threads) == 1) {
		weights = parse_weights(argv[2]);
		dd = false;
	}else if (argc > 2
	    && sscanf(argv[1], "syncwastardd-%u", &threads) == 1) {
		weights = parse_weights(argv[2]);
		dd = true;
	}
	else{
		cerr << "bad input" << endl;
		exit(EXIT_FAILURE);
	}

	for(vector<double>::iterator i = weights->begin();
	    i != weights->end(); i++){
		Tiles *g = (Tiles*)malloc(sizeof(*g_orig));
		memcpy(g, g_orig, sizeof(*g_orig));
		g->set_projection(project);

		Tiles::ManhattanDist *manhattan = new Tiles::ManhattanDist(g);
		manhattan->set_weight(*i);
		g->set_heuristic(manhattan);
		inits->push_back(g->initial_state());
	}

	search = new SyncWAStar::SyncWAStar(threads, inits, dd);

#if defined(NDEBUG)
	timeout(timelimit);
#endif	// NDEBUG

	timer.start();
	path = search->search(&timer, NULL);
	timer.stop();

#if defined(NDEBUG)
	timeout_stop();
#endif	// NDEBUG

	search->output_stats();

	/* Print the graph to the terminal */
//	g.print(cout, path);

	if (path) {
		printf("cost: %f\n", (double) path->at(0)->get_g() / fp_one);
		cout << "length: " << path->size() << endl;

		// Make sure that the heuristic was actually admissible!
		for (unsigned int i = path->size() - 1; i >= 0; i -= 1) {
#if !defined(NDEBUG)
			State *s = path->at(i);
			fp_type togo = path->at(0)->get_g() - s->get_g();
			assert(s->get_h() <= togo);
#endif
			if (i > 0)
				assert(s->get_h() > 0);
			if (i == 0)
				break;
		}

		for (unsigned int i = 0; i < path->size(); i += 1)
			delete path->at(i);
		delete path;
	} else {
		cout << "# No Solution" << endl;
	}
	cout << "time-limit: " << timelimit << endl;
	cout << "wall_time: " << timer.get_wall_time() << endl;
	cout << "CPU_time: " << timer.get_processor_time() << endl;
	cout << "generated: " << search->get_generated() << endl;
	cout << "expanded: " << search->get_expanded() << endl;

	if (project)
		delete project;

	delete search;

	return EXIT_SUCCESS;
}
<|endoftext|>