<commit_before>#ifndef VSMC_CORE_STATE_TUPLE_HPP
#define VSMC_CORE_STATE_TUPLE_HPP

#include <vsmc/core/single_particle.hpp>
#include <tuple>
#include <vector>

#define VSMC_RUNTIME_ASSERT_CORE_STATE_TUPLE_COPY_SIZE_MISMATCH \
    VSMC_RUNTIME_ASSERT((N == static_cast<size_type>(this->size())),         \
            ("**StateTuple::copy** SIZE MISMATCH"))

namespace vsmc {

/// \brief Base type of StateTuple
/// \ingroup Core
template <MatrixOrder Order, typename T, typename... Types>
class StateTupleBase
{
    public :

    typedef std::size_t size_type;
    typedef std::tuple<T, Types...> state_tuple_type;
    typedef std::tuple<T *, Types *...> state_tuple_ptr_type;
    typedef std::tuple<const T *, const Types *...> state_tuple_cptr_type;

    template <std::size_t Pos> struct state_type
    {typedef typename std::tuple_element<Pos, state_tuple_type>::type type;};

    struct state_pack_type
    {
        state_pack_type () {}

        state_pack_type (const state_pack_type &other) : data_(other.data_) {}

        state_pack_type &operator= (const state_pack_type &other)
        {data_ = other.data_; return *this;}

#if VSMC_HAS_CXX11_RVALUE_REFERENCES
        state_pack_type (state_pack_type &&other) VSMC_NOEXCEPT :
            data_(cxx11::move(other.data_)) {}

        state_pack_type &operator= (state_pack_type &&other) VSMC_NOEXCEPT
        {data_ = cxx11::move(other.data_); return *this;}
#endif

        state_pack_type (const state_tuple_type &data) : data_(data) {}

        operator state_tuple_type () {return data_;}

        template <std::size_t Pos>
        typename state_type<Pos>::type &get ()
        {return std::get<Pos>(data_);}

        template <std::size_t Pos>
        const typename state_type<Pos>::type &get () const
        {return std::get<Pos>(data_);}

        template <typename Archive>
        void serialize (Archive &ar, const unsigned)
        {serialize(ar, Position<0>());}

        template <typename Archive>
        void serialize (Archive &ar, const unsigned) const
        {serialize(ar, Position<0>());}

        private :

        state_tuple_type data_;
        static VSMC_CONSTEXPR const std::size_t dim_ = sizeof...(Types) + 1;

        template <typename Archive, std::size_t Pos>
        void serialize (Archive &ar, Position<Pos>)
        {
            ar & std::get<Pos>(data_);
            serialize(ar, Position<Pos + 1>());
        }

        template <typename Archive>
        void serialize (Archive &, Position<dim_>) {}

        template <typename Archive, std::size_t Pos>
        void serialize (Archive &ar, Position<Pos>) const
        {
            ar & std::get<Pos>(data_);
            serialize(ar, Position<Pos + 1>());
        }

        template <typename Archive>
        void serialize (Archive &, Position<dim_>) const {}
    }; // struct state_pack_type

    template <typename S>
    struct single_particle_type : public SingleParticleBase<S>
    {
        single_particle_type (typename Particle<S>::size_type id,
                Particle<S> *particle_ptr) :
            SingleParticleBase<S>(id, particle_ptr) {}

        static VSMC_CONSTEXPR std::size_t dim () {return S::dim();}

        template <std::size_t Pos>
        typename state_type<Pos>::type &state (Position<Pos>) const
        {
            return this->mutable_particle_ptr()->value().
                state(this->id(), Position<Pos>());
        }

        template <std::size_t Pos>
        typename state_type<Pos>::type &state () const
        {return this->state(Position<Pos>());}
    }; // struct single_particle_type

    template <typename S>
    struct const_single_particle_type : public ConstSingleParticleBase<S>
    {
        const_single_particle_type (typename Particle<S>::size_type id,
                const Particle<S> *particle_ptr) :
            ConstSingleParticleBase<S>(id, particle_ptr) {}

        static VSMC_CONSTEXPR std::size_t dim () {return S::dim();}

        template <std::size_t Pos>
        const typename state_type<Pos>::type &state (Position<Pos>) const
        {
            return this->particle_ptr()->value().
                state(this->id(), Position<Pos>());
        }

        template <std::size_t Pos>
        const typename state_type<Pos>::type &state () const
        {return this->state(Position<Pos>());}
    }; // struct const_single_particle_type

    size_type size () const {return size_;}

    static VSMC_CONSTEXPR std::size_t dim () {return dim_;}

    state_pack_type state_pack (size_type id) const
    {
        state_pack_type pack;
        pack_particle(id, pack, Position<0>());

        return pack;
    }

    void state_unpack (size_type id, const state_pack_type &pack)
    {unpack_particle(id, pack, Position<0>());}

    template <typename IntType>
    void copy (size_type N, const IntType *copy_from)
    {
        VSMC_RUNTIME_ASSERT_CORE_STATE_TUPLE_COPY_SIZE_MISMATCH;

        for (size_type to = 0; to != N; ++to)
            copy_particle(copy_from[to], to);
    }

    template <std::size_t Pos, typename OutputIter>
    OutputIter read_state (Position<Pos>, OutputIter first) const
    {
        const StateTuple<Order, T, Types...> *sptr =
            static_cast<const StateTuple<Order, T, Types...> *>(this);
        for (size_type i = 0; i != size_; ++i, ++first)
                *first = sptr->state(i, Position<Pos>());

        return first;
    }

    template <std::size_t Pos, typename OutputIter>
    OutputIter read_state (OutputIter first) const
    {return read_state(Position<Pos>(), first);}

    template <typename CharT, typename Traits>
    std::basic_ostream<CharT, Traits> &print (
            std::basic_ostream<CharT, Traits> &os, std::size_t iter = 0,
            char sepchar = ' ', char eolchar = '\n') const
    {
        for (size_type i = 0; i != size_; ++i) {
            os << iter << sepchar;
            print_particle(os, i, sepchar, eolchar, Position<0>());
        }

        return os;
    }

    protected :

    explicit StateTupleBase (size_type N) : size_(N) {}

    void copy_particle (size_type from, size_type to)
    {
        if (from != to)
            copy_particle(from, to, Position<0>());
    }

    private :

    size_type size_;
    static VSMC_CONSTEXPR const std::size_t dim_ = sizeof...(Types) + 1;

    template <std::size_t Pos>
    void pack_particle (size_type id, state_pack_type &pack,
            Position<Pos>) const
    {
        const StateTuple<Order, T, Types...> *sptr =
            static_cast<const StateTuple<Order, T, Types...> *>(this);
        pack.template get<Pos>() = sptr->state(id, Position<Pos>());
        pack_particle(id, pack, Position<Pos + 1>());
    }

    void pack_particle (size_type, state_pack_type &,
            Position<dim_>) const {}

    template <std::size_t Pos>
    void unpack_particle (size_type id, const state_pack_type &pack,
            Position<Pos>)
    {
        StateTuple<Order, T, Types...> *sptr =
            static_cast<StateTuple<Order, T, Types...> *>(this);
        sptr->state(id, Position<Pos>()) = pack.template get<Pos>();
        unpack_particle(id, pack, Position<Pos + 1>());
    }

    void unpack_particle (size_type, const state_pack_type &,
            Position<dim_>) {}

    template <std::size_t Pos>
    void copy_particle (size_type from, size_type to, Position<Pos>)
    {
        StateTuple<Order, T, Types...> *sptr =
            static_cast<StateTuple<Order, T, Types...> *>(this);
        sptr->state(to, Position<Pos>()) = sptr->state(from, Position<Pos>());
        copy_particle(from, to, Position<Pos + 1>());
    }

    void copy_particle (size_type, size_type, Position<dim_>) {}

    template <std::size_t Pos, typename CharT, typename Traits>
    void print_particle (std::basic_ostream<CharT, Traits> &os, size_type id,
            char sepchar, char eolchar, Position<Pos>) const
    {
        const StateTuple<Order, T, Types...> *sptr =
            static_cast<const StateTuple<Order, T, Types...> *>(this);
        os << sptr->state(id, Position<Pos>()) << sepchar;
        print_particle(os, id, sepchar, eolchar, Position<Pos + 1>());
    }

    template <typename CharT, typename Traits>
    void print_particle (std::basic_ostream<CharT, Traits> &os, size_type id,
            char, char eolchar, Position<dim_ - 1>) const
    {
        const StateTuple<Order, T, Types...> *sptr =
            static_cast<const StateTuple<Order, T, Types...> *>(this);
        os << sptr->state(id, Position<dim_ - 1>()) << eolchar;
    }
}; // class StateTupleBase

/// \brief Particle::value_type subtype
/// \ingroup Core
template <typename T, typename... Types>
class StateTuple<RowMajor, T, Types...> :
    public StateTupleBase<RowMajor, T, Types...>
{
    public :

    typedef StateTupleBase<RowMajor, T, Types...>
        state_tuple_base_type;
    typedef typename state_tuple_base_type::size_type size_type;

    explicit StateTuple (size_type N) : state_tuple_base_type(N), state_(N) {}

    template <std::size_t Pos>
    typename state_tuple_base_type::template state_type<Pos>::type
    &state (size_type id, Position<Pos>)
    {return std::get<Pos>(state_[id]);}

    template <std::size_t Pos>
    const typename state_tuple_base_type::template state_type<Pos>::type
    &state (size_type id, Position<Pos>) const
    {return std::get<Pos>(state_[id]);}

    template <std::size_t Pos>
    typename state_tuple_base_type::template state_type<Pos>::type
    &state (size_type id)
    {return state(id, Position<Pos>());}

    template <std::size_t Pos>
    const typename state_tuple_base_type::template state_type<Pos>::type
    &state (size_type id) const
    {return state(id, Position<Pos>());}

    const typename state_tuple_base_type::state_tuple_type *data () const
    {return &state_[0];}

    private :

    static VSMC_CONSTEXPR const std::size_t dim_ = sizeof...(Types) + 1;
    std::vector<std::tuple<T, Types...> > state_;
}; // StateTuple

/// \brief Particle::value_type subtype
/// \ingroup Core
template <typename T, typename... Types>
class StateTuple<ColMajor, T, Types...> :
    public StateTupleBase<ColMajor, T, Types...>
{
    public :

    typedef StateTupleBase<ColMajor, T, Types...>
        state_tuple_base_type;
    typedef typename state_tuple_base_type::size_type size_type;

    explicit StateTuple (size_type N) : state_tuple_base_type(N)
    {init_state(N, Position<0>());}

    template <std::size_t Pos>
    typename state_tuple_base_type::template state_type<Pos>::type
    &state (size_type id, Position<Pos>)
    {return std::get<Pos>(state_)[id];}

    template <std::size_t Pos>
    const typename state_tuple_base_type::template state_type<Pos>::type
    &state (size_type id, Position<Pos>) const
    {return std::get<Pos>(state_)[id];}

    template <std::size_t Pos>
    typename state_tuple_base_type::template state_type<Pos>::type
    &state (size_type id)
    {return state(id, Position<Pos>());}

    template <std::size_t Pos>
    const typename state_tuple_base_type::template state_type<Pos>::type
    &state (size_type id) const
    {return state(id, Position<Pos>());}

    template <std::size_t Pos>
    const typename state_tuple_base_type::template state_type<Pos>::type
    *data (Position<Pos>) const {return &std::get<Pos>(state_)[0];}

    template <std::size_t Pos>
    const typename state_tuple_base_type::template state_type<Pos>::type
    *data () const {return &std::get<Pos>(state_)[0];}

    typename state_tuple_base_type::state_tuple_cptr_type data () const
    {
        typename state_tuple_base_type::state_tuple_cptr_type dptr;
        insert_data(dptr, Position<0>());

        return dptr;
    }

    private :

    static VSMC_CONSTEXPR const std::size_t dim_ = sizeof...(Types) + 1;
    std::tuple<std::vector<T>, std::vector<Types>...> state_;

    template <std::size_t Pos>
    void init_state (size_type N, Position<Pos>)
    {
        std::get<Pos>(state_).resize(N);
        init_state(N, Position<Pos + 1>());
    }

    void init_state (size_type N, Position<sizeof...(Types)>)
    {std::get<sizeof...(Types)>(state_).resize(N);}

    template <std::size_t Pos>
    void insert_data (
            typename state_tuple_base_type::state_tuple_cptr_type &dptr,
            Position<Pos>) const
    {
        std::get<Pos>(dptr) = data<Pos>();
        insert_data(dptr, Position<Pos + 1>());
    }

    void insert_data (
            typename state_tuple_base_type::state_tuple_cptr_type &dptr,
            Position<sizeof...(Types)>) const
    {std::get<sizeof...(Types)>(dptr) = data<sizeof...(Types)>();}
}; // class StateTuple

} // namespace vsmc

#endif // VSMC_CORE_STATE_TUPLE_HPP
<commit_msg>add mutable data pointer to state tuple<commit_after>#ifndef VSMC_CORE_STATE_TUPLE_HPP
#define VSMC_CORE_STATE_TUPLE_HPP

#include <vsmc/core/single_particle.hpp>
#include <tuple>
#include <vector>

#define VSMC_RUNTIME_ASSERT_CORE_STATE_TUPLE_COPY_SIZE_MISMATCH \
    VSMC_RUNTIME_ASSERT((N == static_cast<size_type>(this->size())),         \
            ("**StateTuple::copy** SIZE MISMATCH"))

namespace vsmc {

/// \brief Base type of StateTuple
/// \ingroup Core
template <MatrixOrder Order, typename T, typename... Types>
class StateTupleBase
{
    public :

    typedef std::size_t size_type;
    typedef std::tuple<T, Types...> state_tuple_type;
    typedef std::tuple<T *, Types *...> state_tuple_ptr_type;
    typedef std::tuple<const T *, const Types *...> state_tuple_cptr_type;

    template <std::size_t Pos> struct state_type
    {typedef typename std::tuple_element<Pos, state_tuple_type>::type type;};

    struct state_pack_type
    {
        state_pack_type () {}

        state_pack_type (const state_pack_type &other) : data_(other.data_) {}

        state_pack_type &operator= (const state_pack_type &other)
        {data_ = other.data_; return *this;}

#if VSMC_HAS_CXX11_RVALUE_REFERENCES
        state_pack_type (state_pack_type &&other) VSMC_NOEXCEPT :
            data_(cxx11::move(other.data_)) {}

        state_pack_type &operator= (state_pack_type &&other) VSMC_NOEXCEPT
        {data_ = cxx11::move(other.data_); return *this;}
#endif

        state_pack_type (const state_tuple_type &data) : data_(data) {}

        operator state_tuple_type () {return data_;}

        template <std::size_t Pos>
        typename state_type<Pos>::type &get ()
        {return std::get<Pos>(data_);}

        template <std::size_t Pos>
        const typename state_type<Pos>::type &get () const
        {return std::get<Pos>(data_);}

        template <typename Archive>
        void serialize (Archive &ar, const unsigned)
        {serialize(ar, Position<0>());}

        template <typename Archive>
        void serialize (Archive &ar, const unsigned) const
        {serialize(ar, Position<0>());}

        private :

        state_tuple_type data_;
        static VSMC_CONSTEXPR const std::size_t dim_ = sizeof...(Types) + 1;

        template <typename Archive, std::size_t Pos>
        void serialize (Archive &ar, Position<Pos>)
        {
            ar & std::get<Pos>(data_);
            serialize(ar, Position<Pos + 1>());
        }

        template <typename Archive>
        void serialize (Archive &, Position<dim_>) {}

        template <typename Archive, std::size_t Pos>
        void serialize (Archive &ar, Position<Pos>) const
        {
            ar & std::get<Pos>(data_);
            serialize(ar, Position<Pos + 1>());
        }

        template <typename Archive>
        void serialize (Archive &, Position<dim_>) const {}
    }; // struct state_pack_type

    template <typename S>
    struct single_particle_type : public SingleParticleBase<S>
    {
        single_particle_type (typename Particle<S>::size_type id,
                Particle<S> *particle_ptr) :
            SingleParticleBase<S>(id, particle_ptr) {}

        static VSMC_CONSTEXPR std::size_t dim () {return S::dim();}

        template <std::size_t Pos>
        typename state_type<Pos>::type &state (Position<Pos>) const
        {
            return this->mutable_particle_ptr()->value().
                state(this->id(), Position<Pos>());
        }

        template <std::size_t Pos>
        typename state_type<Pos>::type &state () const
        {return this->state(Position<Pos>());}
    }; // struct single_particle_type

    template <typename S>
    struct const_single_particle_type : public ConstSingleParticleBase<S>
    {
        const_single_particle_type (typename Particle<S>::size_type id,
                const Particle<S> *particle_ptr) :
            ConstSingleParticleBase<S>(id, particle_ptr) {}

        static VSMC_CONSTEXPR std::size_t dim () {return S::dim();}

        template <std::size_t Pos>
        const typename state_type<Pos>::type &state (Position<Pos>) const
        {
            return this->particle_ptr()->value().
                state(this->id(), Position<Pos>());
        }

        template <std::size_t Pos>
        const typename state_type<Pos>::type &state () const
        {return this->state(Position<Pos>());}
    }; // struct const_single_particle_type

    size_type size () const {return size_;}

    static VSMC_CONSTEXPR std::size_t dim () {return dim_;}

    state_pack_type state_pack (size_type id) const
    {
        state_pack_type pack;
        pack_particle(id, pack, Position<0>());

        return pack;
    }

    void state_unpack (size_type id, const state_pack_type &pack)
    {unpack_particle(id, pack, Position<0>());}

    template <typename IntType>
    void copy (size_type N, const IntType *copy_from)
    {
        VSMC_RUNTIME_ASSERT_CORE_STATE_TUPLE_COPY_SIZE_MISMATCH;

        for (size_type to = 0; to != N; ++to)
            copy_particle(copy_from[to], to);
    }

    template <std::size_t Pos, typename OutputIter>
    OutputIter read_state (Position<Pos>, OutputIter first) const
    {
        const StateTuple<Order, T, Types...> *sptr =
            static_cast<const StateTuple<Order, T, Types...> *>(this);
        for (size_type i = 0; i != size_; ++i, ++first)
                *first = sptr->state(i, Position<Pos>());

        return first;
    }

    template <std::size_t Pos, typename OutputIter>
    OutputIter read_state (OutputIter first) const
    {return read_state(Position<Pos>(), first);}

    template <typename CharT, typename Traits>
    std::basic_ostream<CharT, Traits> &print (
            std::basic_ostream<CharT, Traits> &os, std::size_t iter = 0,
            char sepchar = ' ', char eolchar = '\n') const
    {
        for (size_type i = 0; i != size_; ++i) {
            os << iter << sepchar;
            print_particle(os, i, sepchar, eolchar, Position<0>());
        }

        return os;
    }

    protected :

    explicit StateTupleBase (size_type N) : size_(N) {}

    void copy_particle (size_type from, size_type to)
    {
        if (from != to)
            copy_particle(from, to, Position<0>());
    }

    private :

    size_type size_;
    static VSMC_CONSTEXPR const std::size_t dim_ = sizeof...(Types) + 1;

    template <std::size_t Pos>
    void pack_particle (size_type id, state_pack_type &pack,
            Position<Pos>) const
    {
        const StateTuple<Order, T, Types...> *sptr =
            static_cast<const StateTuple<Order, T, Types...> *>(this);
        pack.template get<Pos>() = sptr->state(id, Position<Pos>());
        pack_particle(id, pack, Position<Pos + 1>());
    }

    void pack_particle (size_type, state_pack_type &,
            Position<dim_>) const {}

    template <std::size_t Pos>
    void unpack_particle (size_type id, const state_pack_type &pack,
            Position<Pos>)
    {
        StateTuple<Order, T, Types...> *sptr =
            static_cast<StateTuple<Order, T, Types...> *>(this);
        sptr->state(id, Position<Pos>()) = pack.template get<Pos>();
        unpack_particle(id, pack, Position<Pos + 1>());
    }

    void unpack_particle (size_type, const state_pack_type &,
            Position<dim_>) {}

    template <std::size_t Pos>
    void copy_particle (size_type from, size_type to, Position<Pos>)
    {
        StateTuple<Order, T, Types...> *sptr =
            static_cast<StateTuple<Order, T, Types...> *>(this);
        sptr->state(to, Position<Pos>()) = sptr->state(from, Position<Pos>());
        copy_particle(from, to, Position<Pos + 1>());
    }

    void copy_particle (size_type, size_type, Position<dim_>) {}

    template <std::size_t Pos, typename CharT, typename Traits>
    void print_particle (std::basic_ostream<CharT, Traits> &os, size_type id,
            char sepchar, char eolchar, Position<Pos>) const
    {
        const StateTuple<Order, T, Types...> *sptr =
            static_cast<const StateTuple<Order, T, Types...> *>(this);
        os << sptr->state(id, Position<Pos>()) << sepchar;
        print_particle(os, id, sepchar, eolchar, Position<Pos + 1>());
    }

    template <typename CharT, typename Traits>
    void print_particle (std::basic_ostream<CharT, Traits> &os, size_type id,
            char, char eolchar, Position<dim_ - 1>) const
    {
        const StateTuple<Order, T, Types...> *sptr =
            static_cast<const StateTuple<Order, T, Types...> *>(this);
        os << sptr->state(id, Position<dim_ - 1>()) << eolchar;
    }
}; // class StateTupleBase

/// \brief Particle::value_type subtype
/// \ingroup Core
template <typename T, typename... Types>
class StateTuple<RowMajor, T, Types...> :
    public StateTupleBase<RowMajor, T, Types...>
{
    public :

    typedef StateTupleBase<RowMajor, T, Types...>
        state_tuple_base_type;
    typedef typename state_tuple_base_type::size_type size_type;

    explicit StateTuple (size_type N) : state_tuple_base_type(N), state_(N) {}

    template <std::size_t Pos>
    typename state_tuple_base_type::template state_type<Pos>::type
    &state (size_type id, Position<Pos>)
    {return std::get<Pos>(state_[id]);}

    template <std::size_t Pos>
    const typename state_tuple_base_type::template state_type<Pos>::type
    &state (size_type id, Position<Pos>) const
    {return std::get<Pos>(state_[id]);}

    template <std::size_t Pos>
    typename state_tuple_base_type::template state_type<Pos>::type
    &state (size_type id)
    {return state(id, Position<Pos>());}

    template <std::size_t Pos>
    const typename state_tuple_base_type::template state_type<Pos>::type
    &state (size_type id) const
    {return state(id, Position<Pos>());}

    typename state_tuple_base_type::state_tuple_type *data ()
    {return &state_[0];}

    const typename state_tuple_base_type::state_tuple_type *data () const
    {return &state_[0];}

    private :

    static VSMC_CONSTEXPR const std::size_t dim_ = sizeof...(Types) + 1;
    std::vector<std::tuple<T, Types...> > state_;
}; // StateTuple

/// \brief Particle::value_type subtype
/// \ingroup Core
template <typename T, typename... Types>
class StateTuple<ColMajor, T, Types...> :
    public StateTupleBase<ColMajor, T, Types...>
{
    public :

    typedef StateTupleBase<ColMajor, T, Types...>
        state_tuple_base_type;
    typedef typename state_tuple_base_type::size_type size_type;

    explicit StateTuple (size_type N) : state_tuple_base_type(N)
    {init_state(N, Position<0>());}

    template <std::size_t Pos>
    typename state_tuple_base_type::template state_type<Pos>::type
    &state (size_type id, Position<Pos>)
    {return std::get<Pos>(state_)[id];}

    template <std::size_t Pos>
    const typename state_tuple_base_type::template state_type<Pos>::type
    &state (size_type id, Position<Pos>) const
    {return std::get<Pos>(state_)[id];}

    template <std::size_t Pos>
    typename state_tuple_base_type::template state_type<Pos>::type
    &state (size_type id)
    {return state(id, Position<Pos>());}

    template <std::size_t Pos>
    const typename state_tuple_base_type::template state_type<Pos>::type
    &state (size_type id) const
    {return state(id, Position<Pos>());}

    template <std::size_t Pos>
    typename state_tuple_base_type::template state_type<Pos>::type
    *data (Position<Pos>) {return &std::get<Pos>(state_)[0];}

    template <std::size_t Pos>
    const typename state_tuple_base_type::template state_type<Pos>::type
    *data (Position<Pos>) const {return &std::get<Pos>(state_)[0];}

    template <std::size_t Pos>
    typename state_tuple_base_type::template state_type<Pos>::type
    *data () {return &std::get<Pos>(state_)[0];}

    template <std::size_t Pos>
    const typename state_tuple_base_type::template state_type<Pos>::type
    *data () const {return &std::get<Pos>(state_)[0];}

    typename state_tuple_base_type::state_tuple_cptr_type data () const
    {
        typename state_tuple_base_type::state_tuple_cptr_type dptr;
        insert_data(dptr, Position<0>());

        return dptr;
    }

    private :

    static VSMC_CONSTEXPR const std::size_t dim_ = sizeof...(Types) + 1;
    std::tuple<std::vector<T>, std::vector<Types>...> state_;

    template <std::size_t Pos>
    void init_state (size_type N, Position<Pos>)
    {
        std::get<Pos>(state_).resize(N);
        init_state(N, Position<Pos + 1>());
    }

    void init_state (size_type N, Position<sizeof...(Types)>)
    {std::get<sizeof...(Types)>(state_).resize(N);}

    template <std::size_t Pos>
    void insert_data (
            typename state_tuple_base_type::state_tuple_cptr_type &dptr,
            Position<Pos>) const
    {
        std::get<Pos>(dptr) = data<Pos>();
        insert_data(dptr, Position<Pos + 1>());
    }

    void insert_data (
            typename state_tuple_base_type::state_tuple_cptr_type &dptr,
            Position<sizeof...(Types)>) const
    {std::get<sizeof...(Types)>(dptr) = data<sizeof...(Types)>();}
}; // class StateTuple

} // namespace vsmc

#endif // VSMC_CORE_STATE_TUPLE_HPP
<|endoftext|>


<commit_before>#include <iostream>
#include <algorithm>
#include <vector>
#include "Suffstats.h"
#include "RandomNumberGenerator.h"
#include "utils.h"

using namespace std;

typedef Suffstats<double> suffD;

int main(int argc, char** argv) {
  cout << endl << "Begin:: test_suffstats" << endl;
  RandomNumberGenerator rng;

  // test settings
  int max_randi = 30;
  int num_values_to_test = 10;
  double precision = 1E-10;

  // generate all the random data to use
  //
  // initial parameters
  double r0 = rng.nexti(max_randi) * rng.next();
  double nu0 = rng.nexti(max_randi) * rng.next();
  double s0 = rng.nexti(max_randi) * rng.next();
  double mu0 = rng.nexti(max_randi) * rng.next();
  //
  // elements to add
  vector<double> values_to_test;
  for(int i=0; i<num_values_to_test; i++) {
    double rand_value = rng.nexti(max_randi) * rng.next();
    values_to_test.push_back(rand_value);
  }
  // remove in a reversed order and a different order
  vector<double> values_to_test_reversed = values_to_test;
  std::reverse(values_to_test_reversed.begin(), values_to_test_reversed.end());
  vector<double> values_to_test_shuffled = values_to_test;
  std::random_shuffle(values_to_test_shuffled.begin(), values_to_test_shuffled.end());

  // print generated values
  //
  cout << endl << "initial parameters: " << "\t";
  cout << "r0: " << r0 << "\t";
  cout << "nu0: " << nu0 << "\t";
  cout << "s0: " << s0 << "\t";
  cout << "mu0: " << mu0 << endl;
  cout << "values_to_test: " << values_to_test << endl;
  cout << "values_to_test_shuffled: " << values_to_test_shuffled << endl;

  // FIXME: should compare with a fixed dataset with known
  // post-update hyper values and score

  // FIXME: should be manually calling numerics:: functions
  // to compare suffstats results with

  // create the suffstats object
  //
  //       r, nu, s, mu
  suffD sd(r0, nu0, s0, mu0);
  cout << endl << "initial suffstats object" << endl;
  cout << sd << endl;
  //
  print_defaults();

  // verify initial parameters
  //
  int count;
  double sum_x, sum_x_sq;
  double r, nu, s, mu;
  sd.get_suffstats(count, sum_x, sum_x_sq);
  sd.get_hypers(r, nu, s, mu);
  assert(count==0);
  assert(is_almost(sum_x, 0, precision));
  assert(is_almost(sum_x_sq, 0, precision));
  assert(is_almost(r, r0, precision));
  assert(is_almost(nu, nu0, precision));
  assert(is_almost(s, s0, precision));
  assert(is_almost(mu, mu0, precision));
  assert(is_almost(sd.get_score(), 0, precision));

  // push data into suffstats
  for(vector<double>::iterator it=values_to_test.begin(); it!=values_to_test.end(); it++) {
    sd.insert_el(*it);
  }
  cout << endl << "suffstats after insertion of data" << endl;
  cout << sd << endl;
  // ensure count is proper
  assert(sd.get_count()==num_values_to_test);
  // remove data from suffstats in REVERSED order
  for(vector<double>::iterator it=values_to_test_reversed.begin(); it!=values_to_test_reversed.end(); it++) {
    sd.remove_el(*it);
  }
  cout << endl << "suffstats after removal of data in reversed order" << endl;
  cout << sd << endl;
  // ensure initial values are recovered
  sd.get_suffstats(count, sum_x, sum_x_sq);
  sd.get_hypers(r, nu, s, mu);
  assert(count==0);
  assert(is_almost(sum_x, 0, precision));
  assert(is_almost(sum_x_sq, 0, precision));
  assert(is_almost(r, r0, precision));
  assert(is_almost(nu, nu0, precision));
  assert(is_almost(s, s0, precision));
  assert(is_almost(mu, mu0, precision));
  assert(is_almost(sd.get_score(), 0, precision));

  // push data into suffstats
  for(vector<double>::iterator it=values_to_test.begin(); it!=values_to_test.end(); it++) {
    sd.insert_el(*it);
  }
  cout << endl << "suffstats after insertion of data" << endl;
  cout << sd << endl;
  // ensure count is proper
  assert(sd.get_count()==num_values_to_test);
  // remove data from suffstats in SHUFFLED order
  for(vector<double>::iterator it=values_to_test_shuffled.begin(); it!=values_to_test_shuffled.end(); it++) {
    sd.remove_el(*it);
  }
  cout << endl << "suffstats after removal of data in shuffled order" << endl;
  cout << sd << endl;
  // ensure initial values are recovered
  sd.get_suffstats(count, sum_x, sum_x_sq);
  sd.get_hypers(r, nu, s, mu);
  assert(count==0);
  assert(is_almost(sum_x, 0, precision));
  assert(is_almost(sum_x_sq, 0, precision));
  assert(is_almost(r, r0, precision));
  assert(is_almost(nu, nu0, precision));
  assert(is_almost(s, s0, precision));
  assert(is_almost(mu, mu0, precision));
  assert(is_almost(sd.get_score(), 0, precision));

  cout << "Stop:: test_suffstats" << endl;
}
<commit_msg>create helpers for inserting, removing multiple els<commit_after>#include <iostream>
#include <algorithm>
#include <vector>
#include "Suffstats.h"
#include "RandomNumberGenerator.h"
#include "utils.h"

using namespace std;

typedef Suffstats<double> suffD;

void insert_els(Suffstats<double> &sd, vector<double> els) {
  for(vector<double>::iterator it=els.begin(); it!=els.end(); it++)
    sd.insert_el(*it);
}

void remove_els(Suffstats<double> &sd, vector<double> els) {
  for(vector<double>::iterator it=els.begin(); it!=els.end(); it++)
    sd.remove_el(*it);
}

int main(int argc, char** argv) {
  cout << endl << "Begin:: test_suffstats" << endl;
  RandomNumberGenerator rng;

  // test settings
  int max_randi = 30;
  int num_values_to_test = 10;
  double precision = 1E-10;

  // generate all the random data to use
  //
  // initial parameters
  double r0 = rng.nexti(max_randi) * rng.next();
  double nu0 = rng.nexti(max_randi) * rng.next();
  double s0 = rng.nexti(max_randi) * rng.next();
  double mu0 = rng.nexti(max_randi) * rng.next();
  //
  // elements to add
  vector<double> values_to_test;
  for(int i=0; i<num_values_to_test; i++) {
    double rand_value = rng.nexti(max_randi) * rng.next();
    values_to_test.push_back(rand_value);
  }
  // remove in a reversed order and a different order
  vector<double> values_to_test_reversed = values_to_test;
  std::reverse(values_to_test_reversed.begin(), values_to_test_reversed.end());
  vector<double> values_to_test_shuffled = values_to_test;
  std::random_shuffle(values_to_test_shuffled.begin(), values_to_test_shuffled.end());

  // print generated values
  //
  cout << endl << "initial parameters: " << "\t";
  cout << "r0: " << r0 << "\t";
  cout << "nu0: " << nu0 << "\t";
  cout << "s0: " << s0 << "\t";
  cout << "mu0: " << mu0 << endl;
  cout << "values_to_test: " << values_to_test << endl;
  cout << "values_to_test_shuffled: " << values_to_test_shuffled << endl;

  // FIXME: should compare with a fixed dataset with known
  // post-update hyper values and score

  // FIXME: should be manually calling numerics:: functions
  // to compare suffstats results with

  // create the suffstats object
  //
  //       r, nu, s, mu
  suffD sd(r0, nu0, s0, mu0);
  cout << endl << "initial suffstats object" << endl;
  cout << sd << endl;
  //
  print_defaults();

  // verify initial parameters
  //
  int count;
  double sum_x, sum_x_sq;
  double r, nu, s, mu;
  sd.get_suffstats(count, sum_x, sum_x_sq);
  sd.get_hypers(r, nu, s, mu);
  assert(count==0);
  assert(is_almost(sum_x, 0, precision));
  assert(is_almost(sum_x_sq, 0, precision));
  assert(is_almost(r, r0, precision));
  assert(is_almost(nu, nu0, precision));
  assert(is_almost(s, s0, precision));
  assert(is_almost(mu, mu0, precision));
  assert(is_almost(sd.get_score(), 0, precision));

  // push data into suffstats
  insert_els(sd, values_to_test);
  cout << endl << "suffstats after insertion of data" << endl;
  cout << sd << endl;
  // ensure count is proper
  assert(sd.get_count()==num_values_to_test);
  // remove data from suffstats in REVERSED order
  remove_els(sd, values_to_test_reversed);
  cout << endl << "suffstats after removal of data in reversed order" << endl;
  cout << sd << endl;
  // ensure initial values are recovered
  sd.get_suffstats(count, sum_x, sum_x_sq);
  sd.get_hypers(r, nu, s, mu);
  assert(count==0);
  assert(is_almost(sum_x, 0, precision));
  assert(is_almost(sum_x_sq, 0, precision));
  assert(is_almost(r, r0, precision));
  assert(is_almost(nu, nu0, precision));
  assert(is_almost(s, s0, precision));
  assert(is_almost(mu, mu0, precision));
  assert(is_almost(sd.get_score(), 0, precision));

  // push data into suffstats
  insert_els(sd, values_to_test);
  cout << endl << "suffstats after insertion of data" << endl;
  cout << sd << endl;
  // ensure count is proper
  assert(sd.get_count()==num_values_to_test);
  // remove data from suffstats in SHUFFLED order
  remove_els(sd, values_to_test_shuffled);
  cout << endl << "suffstats after removal of data in shuffled order" << endl;
  cout << sd << endl;
  // ensure initial values are recovered
  sd.get_suffstats(count, sum_x, sum_x_sq);
  sd.get_hypers(r, nu, s, mu);
  assert(count==0);
  assert(is_almost(sum_x, 0, precision));
  assert(is_almost(sum_x_sq, 0, precision));
  assert(is_almost(r, r0, precision));
  assert(is_almost(nu, nu0, precision));
  assert(is_almost(s, s0, precision));
  assert(is_almost(mu, mu0, precision));
  assert(is_almost(sd.get_score(), 0, precision));

  cout << "Stop:: test_suffstats" << endl;
}
<|endoftext|>


<commit_before>//http://lx.lanqiao.org/problem.page?gpid=T30
/*
连号区间数

问题描述
小明这些天一直在思考这样一个奇怪而有趣的问题：

在1~N的某个全排列中有多少个连号区间呢？这里所说的连号区间的定义是：

如果区间[L, R] 里的所有元素（即此排列的第L个到第R个元素）递增排序后能得到一个长度为R-L+1的“连续”数列，则称这个区间连号区间。

当N很小的时候，小明可以很快地算出答案，但是当N变大的时候，问题就不是那么简单了，现在小明需要你的帮助。

输入格式
第一行是一个正整数N (1 <= N <= 50000), 表示全排列的规模。

第二行是N个不同的数字Pi(1 <= Pi <= N)， 表示这N个数字的某一全排列。

输出格式
输出一个整数，表示不同连号区间的数目。

样例输入1
4
3 2 4 1
样例输出1
7
样例输入2
5
3 4 2 5 1
样例输出2
9
*/

//Because the last part use a disjoint set, it is near linear time.

#include <stdio.h>
#include <string.h>
#define N 60000
int n, in[N], ind[N];
int stk[N], top;
int LH[N], RH[N];
int LL[N], RL[N], MX[N];

int print_arr(int s[], int n) {
  for(int i = 0; i < n; ++i) printf("%d ", s[i]); puts("");
}

int getfat(int bc[], int x) {
  if(bc[x] == -1) return x;
  return bc[x] = getfat(bc, bc[x]);
}

void uni(int bc[], int x, int y) {
  x = getfat(bc, x);
  y = getfat(bc, y);
  if(x == y) return;
  bc[x] = y;
}

void push(int x) {
  LL[x] = top;
  stk[top++] = x;
}

int count(int x) {
  int y = getfat(RL, x + 1);
  return top - LL[y] - 1;
}

void clear(int x) {
  while(top > 0 && stk[top - 1] <= x) {
    uni(RL, stk[top - 1], stk[top - 2]);
    --top;
  }
}

int main() {
  while(scanf("%d", &n) != EOF) {
    for(int i = 1; i <= n; ++i) {
      scanf("%d", in + i);
      ind[in[i]] = i;
      MX[i] = i;
    }

    top = 0;
    for(int i = 1; i <= n; ++i) {
      while(top > 0 && stk[top - 1] > in[i]) {
        int j = stk[top - 1];
        RL[j] = i - 1;
        --top;
      }
      if(top == 0) LL[in[i]] = 1;
      else LL[in[i]] = ind[stk[top - 1]] + 1;
      stk[top++] = in[i];
    }
    while(top > 0) {
      int j = stk[top - 1];
      RL[j] = n;
      --top;
    }

    top = 0;
    for(int i = 1; i <= n; ++i) {
      while(top > 0 && stk[top - 1] < in[i]) {
        int j = stk[top - 1];
        RH[j] = in[i];
        --top;
      }
      if(top == 0) LH[in[i]] = n + 1;
      else LH[in[i]] = stk[top - 1];
      stk[top++] = in[i];
    }
    while(top > 0) {
      int j = stk[top - 1];
      RH[j] = n + 1;
      --top;
    }

    //for(int i = 1; i <= n; ++i) printf("%d %d %d %d %d\n", i, LL[i], RL[i], LH[i], RH[i]);

    for(int i = N - 1; i >= 1; --i) {
      int j = i + 1;
      while(LL[i] <= ind[j] && ind[j] <= RL[i]) {
        j = MX[j] + 1;
        if(j > n) break;
      }
      MX[i] = j - 1;
    }

    //for(int i = 1; i <= n; ++i) printf("%d %d\n", i, MX[i]);

    memset(RL, -1, sizeof(RL[0]) * (n + 10));

    top = 0;

    int ans = 1;
    push(n + 1);
    push(n);

    for(int i = n - 1; i >= 1; --i) {
      int tmp = (ind[i + 1] < ind[i] ? LH[i] : RH[i]) - 1;
      clear(tmp);
      push(i);
      //print_arr(stk, top);
      //printf("i %d %d %d %d\n", i, tmp, count(MX[i]), ans);
      ans += count(MX[i]);
    }
    printf("%d\n", ans);
  }
  return 0;
}
<commit_msg>Update lanqiao_T30.cpp<commit_after>//http://lx.lanqiao.org/problem.page?gpid=T30
/*
连号区间数

问题描述
小明这些天一直在思考这样一个奇怪而有趣的问题：

在1~N的某个全排列中有多少个连号区间呢？这里所说的连号区间的定义是：

如果区间[L, R] 里的所有元素（即此排列的第L个到第R个元素）递增排序后能得到一个长度为R-L+1的“连续”数列，则称这个区间连号区间。

当N很小的时候，小明可以很快地算出答案，但是当N变大的时候，问题就不是那么简单了，现在小明需要你的帮助。

输入格式
第一行是一个正整数N (1 <= N <= 50000), 表示全排列的规模。

第二行是N个不同的数字Pi(1 <= Pi <= N)， 表示这N个数字的某一全排列。

输出格式
输出一个整数，表示不同连号区间的数目。

样例输入1
4
3 2 4 1
样例输出1
7
样例输入2
5
3 4 2 5 1
样例输出2
9
*/

//Because the last part use a disjoint set, it is near linear time.

#include <stdio.h>
#include <string.h>
#define N 60000
int n, in[N], ind[N];
int stk[N], top;
int LH[N], RH[N];
int LL[N], RL[N], MX[N];

int print_arr(int s[], int n) {
  for(int i = 0; i < n; ++i) printf("%d ", s[i]); puts("");
}

int getfat(int bc[], int x) {
  if(bc[x] == -1) return x;
  return bc[x] = getfat(bc, bc[x]);
}

void uni(int bc[], int x, int y) {
  x = getfat(bc, x);
  y = getfat(bc, y);
  if(x == y) return;
  bc[x] = y;
}

void push(int x) {
  LL[x] = top;
  stk[top++] = x;
}

int count(int x) {
  int y = getfat(RL, x + 1);
  return top - LL[y] - 1;
}

void clear(int x) {
  while(top > 0 && stk[top - 1] <= x) {
    uni(RL, stk[top - 1], stk[top - 2]);
    --top;
  }
}

int main() {
  while(scanf("%d", &n) != EOF) {
    for(int i = 1; i <= n; ++i) {
      scanf("%d", in + i);
      ind[in[i]] = i;
      MX[i] = i;
    }

    top = 0;
    for(int i = 1; i <= n; ++i) {
      while(top > 0 && stk[top - 1] > in[i]) {
        int j = stk[top - 1];
        RL[j] = i - 1;
        --top;
      }
      if(top == 0) LL[in[i]] = 1;
      else LL[in[i]] = ind[stk[top - 1]] + 1;
      stk[top++] = in[i];
    }
    while(top > 0) {
      int j = stk[top - 1];
      RL[j] = n;
      --top;
    }

    top = 0;
    for(int i = 1; i <= n; ++i) {
      while(top > 0 && stk[top - 1] < in[i]) {
        int j = stk[top - 1];
        RH[j] = in[i];
        --top;
      }
      if(top == 0) LH[in[i]] = n + 1;
      else LH[in[i]] = stk[top - 1];
      stk[top++] = in[i];
    }
    while(top > 0) {
      int j = stk[top - 1];
      RH[j] = n + 1;
      --top;
    }

    //for(int i = 1; i <= n; ++i) printf("%d %d %d %d %d\n", i, LL[i], RL[i], LH[i], RH[i]);

    for(int i = n - 1; i >= 1; --i) {
      int j = i + 1;
      while(LL[i] <= ind[j] && ind[j] <= RL[i]) {
        j = MX[j] + 1;
        if(j > n) break;
      }
      MX[i] = j - 1;
    }

    //for(int i = 1; i <= n; ++i) printf("%d %d\n", i, MX[i]);

    memset(RL, -1, sizeof(RL[0]) * (n + 10));

    top = 0;

    int ans = 1;
    push(n + 1);
    push(n);

    for(int i = n - 1; i >= 1; --i) {
      int tmp = (ind[i + 1] < ind[i] ? LH[i] : RH[i]) - 1;
      clear(tmp);
      push(i);
      //print_arr(stk, top);
      //printf("i %d %d %d %d\n", i, tmp, count(MX[i]), ans);
      ans += count(MX[i]);
    }
    printf("%d\n", ans);
  }
  return 0;
}
<|endoftext|>


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

// This test only works with the GPU backend.

#include "gm/gm.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPaint.h"
#include "include/core/SkRect.h"
#include "include/core/SkSize.h"
#include "include/core/SkString.h"
#include "include/effects/SkGradientShader.h"
#include "include/private/GrTypesPriv.h"
#include "include/private/SkTArray.h"
#include "src/gpu/GrContextPriv.h"
#include "src/gpu/GrProxyProvider.h"
#include "src/gpu/GrRenderTargetContext.h"
#include "src/gpu/GrRenderTargetContextPriv.h"
#include "src/gpu/GrSamplerState.h"
#include "src/gpu/GrTextureProxy.h"
#include "tools/gpu/TestOps.h"

#include <memory>
#include <utility>

namespace skiagm {
/**
 * This GM directly exercises GrTextureEffect::MakeTexelSubset.
 */
class TextureDomainEffect : public GpuGM {
public:
    TextureDomainEffect(GrSamplerState::Filter filter) : fFilter(filter) {
        this->setBGColor(0xFFFFFFFF);
    }

protected:
    SkString onShortName() override {
        SkString name("texture_domain_effect");
        if (fFilter == GrSamplerState::Filter::kBilerp) {
            name.append("_bilerp");
        } else if (fFilter == GrSamplerState::Filter::kMipMap) {
            name.append("_mipmap");
        }
        return name;
    }

    SkISize onISize() override {
        const SkScalar canvasWidth =
                kDrawPad + 2 * ((kTargetWidth + 2 * kDrawPad) * GrSamplerState::kWrapModeCount +
                                kTestPad * GrSamplerState::kWrapModeCount);
        return SkISize::Make(SkScalarCeilToInt(canvasWidth), 800);
    }

    void onOnceBeforeDraw() override {
        fBitmap.allocN32Pixels(kTargetWidth, kTargetHeight);
        SkCanvas canvas(fBitmap);
        canvas.clear(0x00000000);
        SkPaint paint;

        SkColor colors1[] = { SK_ColorCYAN, SK_ColorLTGRAY, SK_ColorGRAY };
        paint.setShader(SkGradientShader::MakeSweep(65.f, 75.f, colors1, nullptr,
                                                    SK_ARRAY_COUNT(colors1)));
        canvas.drawOval(SkRect::MakeXYWH(-5.f, -5.f, kTargetWidth + 10.f, kTargetHeight + 10.f),
                        paint);

        SkColor colors2[] = { SK_ColorMAGENTA, SK_ColorLTGRAY, SK_ColorYELLOW };
        paint.setShader(SkGradientShader::MakeSweep(45.f, 55.f, colors2, nullptr,
                                                    SK_ARRAY_COUNT(colors2)));
        paint.setBlendMode(SkBlendMode::kDarken);
        canvas.drawOval(SkRect::MakeXYWH(-5.f, -5.f, kTargetWidth + 10.f, kTargetHeight + 10.f),
                        paint);

        SkColor colors3[] = { SK_ColorBLUE, SK_ColorLTGRAY, SK_ColorGREEN };
        paint.setShader(SkGradientShader::MakeSweep(25.f, 35.f, colors3, nullptr,
                                                    SK_ARRAY_COUNT(colors3)));
        paint.setBlendMode(SkBlendMode::kLighten);
        canvas.drawOval(SkRect::MakeXYWH(-5.f, -5.f, kTargetWidth + 10.f, kTargetHeight + 10.f),
                        paint);
    }

    DrawResult onDraw(GrContext* context, GrRenderTargetContext* renderTargetContext,
                      SkCanvas* canvas, SkString* errorMsg) override {
        GrProxyProvider* proxyProvider = context->priv().proxyProvider();
        sk_sp<GrTextureProxy> proxy;
        GrMipMapped mipMapped = fFilter == GrSamplerState::Filter::kMipMap &&
                                context->priv().caps()->mipMapSupport()
                ? GrMipMapped::kYes : GrMipMapped::kNo;
        proxy = proxyProvider->createProxyFromBitmap(fBitmap, mipMapped);
        if (!proxy) {
            *errorMsg = "Failed to create proxy.";
            return DrawResult::kFail;
        }

        SkTArray<SkMatrix> textureMatrices;
        textureMatrices.push_back() = SkMatrix::I();
        textureMatrices.push_back() = SkMatrix::MakeScale(1.5f, 0.85f);
        textureMatrices.push_back();
        textureMatrices.back().setRotate(45.f, proxy->width() / 2.f, proxy->height() / 2.f);

        const SkIRect texelDomains[] = {
            fBitmap.bounds(),
            SkIRect::MakeXYWH(fBitmap.width() / 4 - 1, fBitmap.height() / 4 - 1,
                              fBitmap.width() / 2 + 2, fBitmap.height() / 2 + 2),
        };

        SkRect localRect = SkRect::Make(fBitmap.bounds()).makeOutset(kDrawPad, kDrawPad);

        SkScalar y = kDrawPad + kTestPad;
        for (int tm = 0; tm < textureMatrices.count(); ++tm) {
            for (size_t d = 0; d < SK_ARRAY_COUNT(texelDomains); ++d) {
                SkScalar x = kDrawPad + kTestPad;
                for (int m = 0; m < GrSamplerState::kWrapModeCount; ++m) {
                    auto wm = static_cast<GrSamplerState::WrapMode>(m);
                    if (fFilter != GrSamplerState::Filter::kNearest &&
                        (wm == GrSamplerState::WrapMode::kRepeat ||
                         wm == GrSamplerState::WrapMode::kMirrorRepeat)) {
                        // [Mirror] Repeat mode doesn't produce correct results with bilerp
                        // filtering
                        continue;
                    }
                    GrSamplerState sampler(wm, fFilter);
                    const auto& caps = *context->priv().caps();
                    auto fp1 = GrTextureEffect::MakeTexelSubset(proxy,
                                                                fBitmap.alphaType(),
                                                                textureMatrices[tm],
                                                                sampler,
                                                                texelDomains[d],
                                                                caps);
                    if (!fp1) {
                        continue;
                    }
                    auto fp2 = fp1->clone();
                    SkASSERT(fp2);
                    auto drawRect = localRect.makeOffset(x, y);
                    if (auto op = sk_gpu_test::test_ops::MakeRect(
                                context, std::move(fp1), drawRect, localRect)) {
                        renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
                    }
                    x += localRect.width() + kTestPad;
                    // Draw again with a translated local rect and compensating translate matrix.
                    drawRect = localRect.makeOffset(x, y);
                    static constexpr SkVector kT = {-100, 300};

                    if (auto op = sk_gpu_test::test_ops::MakeRect(context,
                                                                  std::move(fp2),
                                                                  drawRect,
                                                                  localRect.makeOffset(kT),
                                                                  SkMatrix::MakeTrans(-kT))) {
                        renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
                    }
                    x += localRect.width() + kTestPad;
                }
                y += localRect.height() + kTestPad;
            }
        }
        return DrawResult::kOk;
    }

private:
    static constexpr SkScalar kDrawPad = 10.f;
    static constexpr SkScalar kTestPad = 10.f;
    static constexpr int      kTargetWidth = 100;
    static constexpr int      kTargetHeight = 100;
    SkBitmap fBitmap;
    GrSamplerState::Filter fFilter;

    typedef GM INHERITED;
};

DEF_GM(return new TextureDomainEffect(GrSamplerState::Filter::kNearest);)
DEF_GM(return new TextureDomainEffect(GrSamplerState::Filter::kBilerp);)
DEF_GM(return new TextureDomainEffect(GrSamplerState::Filter::kMipMap);)

}
<commit_msg>Revert "Revert "Use bitmap subset for comparison in texture_domain_effect GMs.""<commit_after>/*
 * Copyright 2014 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

// This test only works with the GPU backend.

#include "gm/gm.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPaint.h"
#include "include/core/SkRect.h"
#include "include/core/SkSize.h"
#include "include/core/SkString.h"
#include "include/effects/SkGradientShader.h"
#include "include/private/GrTypesPriv.h"
#include "include/private/SkTArray.h"
#include "src/gpu/GrContextPriv.h"
#include "src/gpu/GrProxyProvider.h"
#include "src/gpu/GrRenderTargetContext.h"
#include "src/gpu/GrRenderTargetContextPriv.h"
#include "src/gpu/GrSamplerState.h"
#include "src/gpu/GrTextureProxy.h"
#include "tools/gpu/TestOps.h"

#include <memory>
#include <utility>

namespace skiagm {
/**
 * This GM directly exercises GrTextureEffect::MakeTexelSubset.
 */
class TextureDomainEffect : public GpuGM {
public:
    TextureDomainEffect(GrSamplerState::Filter filter) : fFilter(filter) {
        this->setBGColor(0xFFFFFFFF);
    }

protected:
    SkString onShortName() override {
        SkString name("texture_domain_effect");
        if (fFilter == GrSamplerState::Filter::kBilerp) {
            name.append("_bilerp");
        } else if (fFilter == GrSamplerState::Filter::kMipMap) {
            name.append("_mipmap");
        }
        return name;
    }

    SkISize onISize() override {
        const SkScalar canvasWidth =
                kDrawPad + 2 * ((kTargetWidth + 2 * kDrawPad) * GrSamplerState::kWrapModeCount +
                                kTestPad * GrSamplerState::kWrapModeCount);
        return SkISize::Make(SkScalarCeilToInt(canvasWidth), 800);
    }

    void onOnceBeforeDraw() override {
        fBitmap.allocN32Pixels(kTargetWidth, kTargetHeight);
        SkCanvas canvas(fBitmap);
        canvas.clear(0x00000000);
        SkPaint paint;

        SkColor colors1[] = { SK_ColorCYAN, SK_ColorLTGRAY, SK_ColorGRAY };
        paint.setShader(SkGradientShader::MakeSweep(65.f, 75.f, colors1, nullptr,
                                                    SK_ARRAY_COUNT(colors1)));
        canvas.drawOval(SkRect::MakeXYWH(-5.f, -5.f, kTargetWidth + 10.f, kTargetHeight + 10.f),
                        paint);

        SkColor colors2[] = { SK_ColorMAGENTA, SK_ColorLTGRAY, SK_ColorYELLOW };
        paint.setShader(SkGradientShader::MakeSweep(45.f, 55.f, colors2, nullptr,
                                                    SK_ARRAY_COUNT(colors2)));
        paint.setBlendMode(SkBlendMode::kDarken);
        canvas.drawOval(SkRect::MakeXYWH(-5.f, -5.f, kTargetWidth + 10.f, kTargetHeight + 10.f),
                        paint);

        SkColor colors3[] = { SK_ColorBLUE, SK_ColorLTGRAY, SK_ColorGREEN };
        paint.setShader(SkGradientShader::MakeSweep(25.f, 35.f, colors3, nullptr,
                                                    SK_ARRAY_COUNT(colors3)));
        paint.setBlendMode(SkBlendMode::kLighten);
        canvas.drawOval(SkRect::MakeXYWH(-5.f, -5.f, kTargetWidth + 10.f, kTargetHeight + 10.f),
                        paint);
    }

    DrawResult onDraw(GrContext* context, GrRenderTargetContext* renderTargetContext,
                      SkCanvas* canvas, SkString* errorMsg) override {
        GrProxyProvider* proxyProvider = context->priv().proxyProvider();
        sk_sp<GrTextureProxy> proxy;
        GrMipMapped mipMapped = fFilter == GrSamplerState::Filter::kMipMap &&
                                context->priv().caps()->mipMapSupport()
                ? GrMipMapped::kYes : GrMipMapped::kNo;
        proxy = proxyProvider->createProxyFromBitmap(fBitmap, mipMapped);
        if (!proxy) {
            *errorMsg = "Failed to create proxy.";
            return DrawResult::kFail;
        }

        SkTArray<SkMatrix> textureMatrices;
        textureMatrices.push_back() = SkMatrix::I();
        textureMatrices.push_back() = SkMatrix::MakeScale(1.5f, 0.85f);
        textureMatrices.push_back();
        textureMatrices.back().setRotate(45.f, proxy->width() / 2.f, proxy->height() / 2.f);

        const SkIRect texelDomains[] = {
            fBitmap.bounds(),
            SkIRect::MakeXYWH(fBitmap.width() / 4 - 1, fBitmap.height() / 4 - 1,
                              fBitmap.width() / 2 + 2, fBitmap.height() / 2 + 2),
        };

        sk_sp<GrTextureProxy> subsetProxies[SK_ARRAY_COUNT(texelDomains)];
        for (size_t d = 0; d < SK_ARRAY_COUNT(texelDomains); ++d) {
            SkBitmap subset;
            fBitmap.extractSubset(&subset, texelDomains[d]);
            subsetProxies[d] = proxyProvider->createProxyFromBitmap(subset, mipMapped);
        }

        SkRect localRect = SkRect::Make(fBitmap.bounds()).makeOutset(kDrawPad, kDrawPad);

        SkScalar y = kDrawPad + kTestPad;
        for (int tm = 0; tm < textureMatrices.count(); ++tm) {
            for (size_t d = 0; d < SK_ARRAY_COUNT(texelDomains); ++d) {
                SkScalar x = kDrawPad + kTestPad;
                for (int m = 0; m < GrSamplerState::kWrapModeCount; ++m) {
                    auto wm = static_cast<GrSamplerState::WrapMode>(m);
                    if (fFilter != GrSamplerState::Filter::kNearest &&
                        (wm == GrSamplerState::WrapMode::kRepeat ||
                         wm == GrSamplerState::WrapMode::kMirrorRepeat)) {
                        // [Mirror] Repeat mode doesn't produce correct results with bilerp
                        // filtering
                        continue;
                    }
                    GrSamplerState sampler(wm, fFilter);
                    const auto& caps = *context->priv().caps();
                    auto fp1 = GrTextureEffect::MakeTexelSubset(proxy,
                                                                fBitmap.alphaType(),
                                                                textureMatrices[tm],
                                                                sampler,
                                                                texelDomains[d],
                                                                caps);
                    if (!fp1) {
                        continue;
                    }
                    auto drawRect = localRect.makeOffset(x, y);
                    // Throw a translate in the local matrix just to test having something other
                    // than identity. Compensate with an offset local rect.
                    static constexpr SkVector kT = {-100, 300};
                    if (auto op = sk_gpu_test::test_ops::MakeRect(context,
                                                                  std::move(fp1),
                                                                  drawRect,
                                                                  localRect.makeOffset(kT),
                                                                  SkMatrix::MakeTrans(-kT))) {
                        renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
                    }
                    x += localRect.width() + kTestPad;

                    SkMatrix subsetTextureMatrix = SkMatrix::Concat(
                            SkMatrix::MakeTrans(-texelDomains[d].topLeft()), textureMatrices[tm]);

                    // Now draw with a subsetted proxy using fixed function texture sampling rather
                    // than a texture subset as a comparison.
                    drawRect = localRect.makeOffset(x, y);
                    auto fp2 = GrTextureEffect::Make(subsetProxies[d], fBitmap.alphaType(),
                                                     subsetTextureMatrix,
                                                     GrSamplerState(wm, fFilter), caps);
                    if (auto op = sk_gpu_test::test_ops::MakeRect(context, std::move(fp2), drawRect,
                                                                  localRect)) {
                        renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
                    }
                    x += localRect.width() + kTestPad;
                }
                y += localRect.height() + kTestPad;
            }
        }
        return DrawResult::kOk;
    }

private:
    static constexpr SkScalar kDrawPad = 10.f;
    static constexpr SkScalar kTestPad = 10.f;
    static constexpr int      kTargetWidth = 100;
    static constexpr int      kTargetHeight = 100;
    SkBitmap fBitmap;
    GrSamplerState::Filter fFilter;

    typedef GM INHERITED;
};

DEF_GM(return new TextureDomainEffect(GrSamplerState::Filter::kNearest);)
DEF_GM(return new TextureDomainEffect(GrSamplerState::Filter::kBilerp);)
DEF_GM(return new TextureDomainEffect(GrSamplerState::Filter::kMipMap);)

}
<|endoftext|>


<commit_before>#include <reactive/bridge.hpp>
#include <reactive/ptr_observable.hpp>
#include <reactive/buffer.hpp>
#include <reactive/generate.hpp>
#include <reactive/tuple.hpp>
#include <reactive/transform.hpp>
#include <reactive/while.hpp>
#include <reactive/finite_state_machine.hpp>
#include <reactive/filter.hpp>
#include <reactive/timer.hpp>
#include <reactive/total_consumer.hpp>
#include <SDL2/SDL.h>
#include <boost/system/system_error.hpp>
#include <boost/scope_exit.hpp>
#include <boost/variant.hpp>
#include <boost/asio.hpp>

namespace
{
	void throw_error()
	{
		throw std::runtime_error(std::string("SDL error :") + SDL_GetError());
	}

	void check_sdl(int rc)
	{
		if (rc < 0)
		{
			throw_error();
		}
	}

	struct window_destructor
	{
		void operator()(SDL_Window *w) const
		{
			SDL_DestroyWindow(w);
		}
	};

	struct renderer_destructor
	{
		void operator()(SDL_Renderer *r) const
		{
			SDL_DestroyRenderer(r);
		}
	};

	struct draw_filled_rect
	{
		SDL_Color color;
		SDL_Rect where;
	};

	typedef boost::variant<
		draw_filled_rect
	> draw_operation;

	struct frame
	{
		std::vector<draw_operation> operations;
	};

	SDL_Color make_color(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha)
	{
		SDL_Color result;
		result.r = red;
		result.g = green;
		result.b = blue;
		result.a = alpha;
		return result;
	}

	SDL_Rect make_rect(int x, int y, int w, int h)
	{
		SDL_Rect result;
		result.x = x;
		result.y = y;
		result.w = w;
		result.h = h;
		return result;
	}

	struct game_state
	{
		int x = 100;
		int y = 100;
		int count = 1;
	};

	int const max_rect_count = 5;

	frame draw_game_state(game_state const &state)
	{
		std::vector<draw_operation> operations;
		for (int i = 0; i < state.count; ++i)
		{
			int const max_width = 80;
			int const single_offset = (max_width / 2) / max_rect_count;
			int const total_offset = single_offset * i;
			int const width = max_width - total_offset * 2;
			operations.emplace_back(draw_filled_rect{make_color(0xff, 0x00, 0x00, 0xff), make_rect(state.x + total_offset, state.y + total_offset, width, width)});
		}
		return frame
		{
			std::move(operations)
		};
	}

	game_state step_game_state(game_state previous, SDL_Event event_)
	{
		switch (event_.type)
		{
		case SDL_KEYUP:
			{
				switch (event_.key.keysym.sym)
				{
				case SDLK_LEFT:
					previous.x -= 10;
					break;

				case SDLK_RIGHT:
					previous.x += 10;
					break;

				case SDLK_UP:
					previous.y -= 10;
					break;

				case SDLK_DOWN:
					previous.y += 10;
					break;

				case SDLK_PLUS:
					previous.count = std::min(max_rect_count, previous.count + 1);
					break;

				case SDLK_MINUS:
					previous.count = std::max(1, previous.count - 1);
					break;
				}
				break;
			}
		}
		return previous;
	}

	template <class Events>
	auto make_frames(Events &&input)
	{
		game_state initial_state;
		auto interesting_input = rx::filter(std::forward<Events>(input), [](SDL_Event const &event_)
		{
			return event_.type == SDL_KEYUP;
		});
		return rx::transform(rx::make_finite_state_machine(interesting_input, initial_state, step_game_state), draw_game_state);
	}

	void set_render_draw_color(SDL_Renderer &renderer, SDL_Color color)
	{
		SDL_SetRenderDrawColor(&renderer, color.r, color.g, color.b, color.a);
	}

	struct draw_operation_renderer : boost::static_visitor<>
	{
		explicit draw_operation_renderer(SDL_Renderer &sdl)
			: sdl(&sdl)
		{
		}

		void operator()(draw_filled_rect const &operation) const
		{
			set_render_draw_color(*sdl, operation.color);
			SDL_RenderDrawRect(sdl, &operation.where);
		}

	private:

		SDL_Renderer *sdl;
	};

	void render_frame(SDL_Renderer &sdl, frame const &frame_)
	{
		set_render_draw_color(sdl, make_color(0, 0, 0, 0xff));
		SDL_RenderClear(&sdl);
		for (auto const &operation : frame_.operations)
		{
			boost::apply_visitor(draw_operation_renderer{sdl}, operation);
		}
		SDL_RenderPresent(&sdl);
	}

	struct frame_renderer : rx::observer<frame>
	{
		explicit frame_renderer(SDL_Renderer &sdl)
			: sdl(&sdl)
		{
		}

		virtual void got_element(frame value) SILICIUM_OVERRIDE
		{
			render_frame(*sdl, value);
		}

		virtual void ended() SILICIUM_OVERRIDE
		{
		}

	private:

		SDL_Renderer *sdl;
	};

	struct quitting
	{
	};

	struct frame_rendered
	{
	};
}

int main()
{
	check_sdl(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS));
	BOOST_SCOPE_EXIT(void)
	{
		SDL_Quit();
	}
	BOOST_SCOPE_EXIT_END;

	std::unique_ptr<SDL_Window, window_destructor> window(SDL_CreateWindow("Silicium react.cpp", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 800, 600, 0));
	if (!window)
	{
		throw_error();
		return 1;
	}

	std::unique_ptr<SDL_Renderer, renderer_destructor> renderer(SDL_CreateRenderer(window.get(), -1, 0));

	rx::bridge<SDL_Event> frame_events;
	auto frames = rx::wrap<frame>(make_frames(while_(rx::ref(frame_events), [](SDL_Event const &event_)
	{
		bool continue_ = event_.type != SDL_QUIT;
		return continue_;
	})));

	boost::asio::io_service io;

	frame_renderer frame_renderer_(*renderer);
	rx::timer frame_rate_limiter(io, boost::posix_time::milliseconds(16));

	auto all_rendered = make_total_consumer(rx::transform(rx::make_tuple(rx::ref(frame_rate_limiter), frames), [&renderer, &frame_events](std::tuple<rx::timer_elapsed, frame> const &ready_frame)
	{
		SDL_Event event;
		while (frame_events.is_waiting() &&
			   SDL_PollEvent(&event))
		{
			frame_events.got_element(event);
		}

		render_frame(*renderer, std::get<1>(ready_frame));
		return frame_rendered{};
	}));
	all_rendered.start();

	io.run();
}
<commit_msg>remove an unused, empty struct<commit_after>#include <reactive/bridge.hpp>
#include <reactive/ptr_observable.hpp>
#include <reactive/buffer.hpp>
#include <reactive/generate.hpp>
#include <reactive/tuple.hpp>
#include <reactive/transform.hpp>
#include <reactive/while.hpp>
#include <reactive/finite_state_machine.hpp>
#include <reactive/filter.hpp>
#include <reactive/timer.hpp>
#include <reactive/total_consumer.hpp>
#include <SDL2/SDL.h>
#include <boost/system/system_error.hpp>
#include <boost/scope_exit.hpp>
#include <boost/variant.hpp>
#include <boost/asio.hpp>

namespace
{
	void throw_error()
	{
		throw std::runtime_error(std::string("SDL error :") + SDL_GetError());
	}

	void check_sdl(int rc)
	{
		if (rc < 0)
		{
			throw_error();
		}
	}

	struct window_destructor
	{
		void operator()(SDL_Window *w) const
		{
			SDL_DestroyWindow(w);
		}
	};

	struct renderer_destructor
	{
		void operator()(SDL_Renderer *r) const
		{
			SDL_DestroyRenderer(r);
		}
	};

	struct draw_filled_rect
	{
		SDL_Color color;
		SDL_Rect where;
	};

	typedef boost::variant<
		draw_filled_rect
	> draw_operation;

	struct frame
	{
		std::vector<draw_operation> operations;
	};

	SDL_Color make_color(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha)
	{
		SDL_Color result;
		result.r = red;
		result.g = green;
		result.b = blue;
		result.a = alpha;
		return result;
	}

	SDL_Rect make_rect(int x, int y, int w, int h)
	{
		SDL_Rect result;
		result.x = x;
		result.y = y;
		result.w = w;
		result.h = h;
		return result;
	}

	struct game_state
	{
		int x = 100;
		int y = 100;
		int count = 1;
	};

	int const max_rect_count = 5;

	frame draw_game_state(game_state const &state)
	{
		std::vector<draw_operation> operations;
		for (int i = 0; i < state.count; ++i)
		{
			int const max_width = 80;
			int const single_offset = (max_width / 2) / max_rect_count;
			int const total_offset = single_offset * i;
			int const width = max_width - total_offset * 2;
			operations.emplace_back(draw_filled_rect{make_color(0xff, 0x00, 0x00, 0xff), make_rect(state.x + total_offset, state.y + total_offset, width, width)});
		}
		return frame
		{
			std::move(operations)
		};
	}

	game_state step_game_state(game_state previous, SDL_Event event_)
	{
		switch (event_.type)
		{
		case SDL_KEYUP:
			{
				switch (event_.key.keysym.sym)
				{
				case SDLK_LEFT:
					previous.x -= 10;
					break;

				case SDLK_RIGHT:
					previous.x += 10;
					break;

				case SDLK_UP:
					previous.y -= 10;
					break;

				case SDLK_DOWN:
					previous.y += 10;
					break;

				case SDLK_PLUS:
					previous.count = std::min(max_rect_count, previous.count + 1);
					break;

				case SDLK_MINUS:
					previous.count = std::max(1, previous.count - 1);
					break;
				}
				break;
			}
		}
		return previous;
	}

	template <class Events>
	auto make_frames(Events &&input)
	{
		game_state initial_state;
		auto interesting_input = rx::filter(std::forward<Events>(input), [](SDL_Event const &event_)
		{
			return event_.type == SDL_KEYUP;
		});
		return rx::transform(rx::make_finite_state_machine(interesting_input, initial_state, step_game_state), draw_game_state);
	}

	void set_render_draw_color(SDL_Renderer &renderer, SDL_Color color)
	{
		SDL_SetRenderDrawColor(&renderer, color.r, color.g, color.b, color.a);
	}

	struct draw_operation_renderer : boost::static_visitor<>
	{
		explicit draw_operation_renderer(SDL_Renderer &sdl)
			: sdl(&sdl)
		{
		}

		void operator()(draw_filled_rect const &operation) const
		{
			set_render_draw_color(*sdl, operation.color);
			SDL_RenderDrawRect(sdl, &operation.where);
		}

	private:

		SDL_Renderer *sdl;
	};

	void render_frame(SDL_Renderer &sdl, frame const &frame_)
	{
		set_render_draw_color(sdl, make_color(0, 0, 0, 0xff));
		SDL_RenderClear(&sdl);
		for (auto const &operation : frame_.operations)
		{
			boost::apply_visitor(draw_operation_renderer{sdl}, operation);
		}
		SDL_RenderPresent(&sdl);
	}

	struct frame_renderer : rx::observer<frame>
	{
		explicit frame_renderer(SDL_Renderer &sdl)
			: sdl(&sdl)
		{
		}

		virtual void got_element(frame value) SILICIUM_OVERRIDE
		{
			render_frame(*sdl, value);
		}

		virtual void ended() SILICIUM_OVERRIDE
		{
		}

	private:

		SDL_Renderer *sdl;
	};

	struct frame_rendered
	{
	};
}

int main()
{
	check_sdl(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS));
	BOOST_SCOPE_EXIT(void)
	{
		SDL_Quit();
	}
	BOOST_SCOPE_EXIT_END;

	std::unique_ptr<SDL_Window, window_destructor> window(SDL_CreateWindow("Silicium react.cpp", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 800, 600, 0));
	if (!window)
	{
		throw_error();
		return 1;
	}

	std::unique_ptr<SDL_Renderer, renderer_destructor> renderer(SDL_CreateRenderer(window.get(), -1, 0));

	rx::bridge<SDL_Event> frame_events;
	auto frames = rx::wrap<frame>(make_frames(while_(rx::ref(frame_events), [](SDL_Event const &event_)
	{
		bool continue_ = event_.type != SDL_QUIT;
		return continue_;
	})));

	boost::asio::io_service io;

	frame_renderer frame_renderer_(*renderer);
	rx::timer frame_rate_limiter(io, boost::posix_time::milliseconds(16));

	auto all_rendered = make_total_consumer(rx::transform(rx::make_tuple(rx::ref(frame_rate_limiter), frames), [&renderer, &frame_events](std::tuple<rx::timer_elapsed, frame> const &ready_frame)
	{
		SDL_Event event;
		while (frame_events.is_waiting() &&
			   SDL_PollEvent(&event))
		{
			frame_events.got_element(event);
		}

		render_frame(*renderer, std::get<1>(ready_frame));
		return frame_rendered{};
	}));
	all_rendered.start();

	io.run();
}
<|endoftext|>


<commit_before>

#pragma pack(push,1)
struct FILE_Object3dHeader
{
    int32_t Version;
    int32_t NumberOfVertexes;
    int32_t NumberOfPrimitives;
    int32_t OffsetToSelectionPrimitive;//Appears to be index into primitive array
    int32_t XFromParent;
    int32_t YFromParent;
    int32_t ZFromParent;
    int32_t OffsetToObjectName;
    int32_t Always_0;
    int32_t OffsetToVertexArray;
    int32_t OffsetToPrimitiveArray;
    int32_t OffsetToSiblingObject;
    int32_t OffsetToChildObject;
};

struct FILE_Object3dVertex
{
    int32_t x;
    int32_t y;
    int32_t z;
};

struct FILE_Object3dPrimitive
{
    int32_t ColorIndex;
    int32_t NumberOfVertexIndexes;
    int32_t Always_0;
    int32_t OffsetToVertexIndexArray;
    int32_t OffsetToTextureName;
    //Apparently Cavedog editor specific:
    int32_t Unknown_1;
    int32_t Unknown_2;
    int32_t Unknown_3;
};
#pragma pack(pop)

struct Position3d
{
    double X,Y,Z;
};

struct Object3d
{
    char * Name;
    Object3d * Children;
    int NumberOfChildren;
    Position3d Position;
    int NumberOfPrimitives;
    struct Object3dPrimitive * Primitives;
    int NumberOfVertices;
    GLfloat * Vertices;
    GLuint VertexBuffer;
    int NumTriangles;
};

struct Object3dPrimitive
{
    Texture * Texture;
    int NumberOfVertices;
    int ColorIndex;
    int * VertexIndexes;
};

void FillObject3dData(GLfloat * Data, int CurrentTriangle,int * VertexIndices,GLfloat * UV, Texture * Texture, Object3d * Object, Object3dPrimitive * Primitive)
{
    int Offset=CurrentTriangle*(3+2+3)*3;
    Data+=Offset;

    for(int i=0;i<3;i++)
    {
	Data[i*8+0]=Object->Vertices[Primitive->VertexIndexes[VertexIndices[i]]*3+0];
	Data[i*8+1]=Object->Vertices[Primitive->VertexIndexes[VertexIndices[i]]*3+1];
	Data[i*8+2]=Object->Vertices[Primitive->VertexIndexes[VertexIndices[i]]*3+2];

	Data[i*8+3]=Texture->U+Texture->Width*UV[i*2+0];
	Data[i*8+4]=Texture->V+Texture->Height*UV[i*2+1];

	Data[i*8+5]=(uint8_t)PaletteData[Primitive->ColorIndex*3+0]/255.0;
	Data[i*8+6]=(uint8_t)PaletteData[Primitive->ColorIndex*3+1]/255.0;
	Data[i*8+7]=(uint8_t)PaletteData[Primitive->ColorIndex*3+2]/255.0;
    }
}

Texture NoTexture={"",0,-2,-2,-1,-1,0};

bool32 PrepareObject3dForRendering(Object3d * Object)
{
    if(Object->VertexBuffer)
    {
	glDeleteVertexArrays(1,&Object->VertexBuffer);
    }

    Object->NumTriangles=0;
    for(int i=0;i<Object->NumberOfPrimitives;i++)
    {
	Object->NumTriangles += Object->Primitives[i].NumberOfVertices-2>0?Object->Primitives[i].NumberOfVertices-2:0;
    }
    GLfloat Data[Object->NumTriangles * (3+2+3)*3];//3 coord, 2 tex, 3 color
    //NOTE: signal no texture in some way, perhaps negative texture coords?
    int CurrentTriangle=0;
    for(int PrimitiveIndex=0;PrimitiveIndex<Object->NumberOfPrimitives;PrimitiveIndex++)
    {
	Object3dPrimitive * CurrentPrimitive=&Object->Primitives[PrimitiveIndex];
	Texture * Texture=CurrentPrimitive->Texture;
	if(!Texture)
	    Texture=&NoTexture;
	switch(CurrentPrimitive->NumberOfVertices)
	{
	case 1:
	case 2:
	    LogDebug("ignoring line or point (%d) in %s",CurrentPrimitive->NumberOfVertices,Object->Name);
	    break;
	case 3:
	{
	    GLfloat UVCoords[]={0,1, 1,1, 0,0};
	    int Vertexes[]={0,1,2};
	    FillObject3dData(Data,CurrentTriangle,Vertexes,UVCoords,Texture,Object,CurrentPrimitive);
	    CurrentTriangle++;
	}
	    break;
	case 4:
	{
	    GLfloat UVCoords1[]={1,0, 0,1, 1,1};
	    int Vertexes1[]={0,2,3};
	    FillObject3dData(Data,CurrentTriangle,Vertexes1,UVCoords1,Texture,Object,CurrentPrimitive);
	    CurrentTriangle++;
	    GLfloat UVCoords2[]={1,0, 0,0, 0,1};
	    int Vertexes2[]={0,1,2};
	    FillObject3dData(Data,CurrentTriangle,Vertexes2,UVCoords2,Texture,Object,CurrentPrimitive);
	    CurrentTriangle++;
	}
	    break;
	default:
	{
	    GLfloat UVCoords[6];
	    //Map sin/cos unit circle at (0,0) onto 1/2 unit circle at (0.5,0.5)
	    UVCoords[2*2]=0.5f*(1-(sin((2.0f*(CurrentPrimitive->NumberOfVertices-1)+1)*PI/float(CurrentPrimitive->NumberOfVertices))/cos(PI/CurrentPrimitive->NumberOfVertices)));
	    UVCoords[2*2+1]=0.5f*(1-(cos(PI/CurrentPrimitive->NumberOfVertices*(2.0f*(CurrentPrimitive->NumberOfVertices-1)+1))/cos(PI/CurrentPrimitive->NumberOfVertices)));

	    for(int i=0;i<CurrentPrimitive->NumberOfVertices-2;i++)
	    {
		int Vertexes[]={i,i+1,CurrentPrimitive->NumberOfVertices-1};

		for(int j=0;j<2;j++)
		{
		    //Map sin/cos unit circle at (0,0) onto 1/2 unit circle at (0.5,0.5)
		    UVCoords[j*2]=0.5f*(1-(sin((2.0f*(i+j)+1)*PI/float(CurrentPrimitive->NumberOfVertices))/cos(PI/CurrentPrimitive->NumberOfVertices)));
		    UVCoords[j*2+1]=0.5f*(1-(cos(PI/CurrentPrimitive->NumberOfVertices*(2.0f*(i+j)+1))/cos(PI/CurrentPrimitive->NumberOfVertices)));
		}
		FillObject3dData(Data,CurrentTriangle,Vertexes,UVCoords,Texture,Object,CurrentPrimitive);
		CurrentTriangle++;
	    }
	}
	    break;
	}
    }

    glGenVertexArrays(1,&Object->VertexBuffer);
    glBindVertexArray(Object->VertexBuffer);

    GLuint VertexBuffer;
    glGenBuffers(1,&VertexBuffer);

    glBindBuffer(GL_ARRAY_BUFFER,VertexBuffer);
    glBufferData(GL_ARRAY_BUFFER,sizeof(GLfloat)*Object->NumTriangles*(3+2+3)*3,Data,GL_STATIC_DRAW);
    glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,sizeof(GLfloat)*(3+2+3),0);
    glVertexAttribPointer(1,2,GL_FLOAT,GL_FALSE,sizeof(GLfloat)*(3+2+3),(GLvoid*)(sizeof(GLfloat)*3));

    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);

    glVertexAttribPointer(2,3,GL_FLOAT,GL_FALSE,sizeof(GLfloat)*(3+2+3),(GLvoid*)(sizeof(GLfloat)*5));
    glEnableVertexAttribArray(2);

    glBindVertexArray(0);
    //glDeleteBuffers(1,&VertexBuffer);

    for(int i=0;i<Object->NumberOfChildren;i++)
    {
	if(!PrepareObject3dForRendering(&Object->Children[i]))
	    return 0;
    }

    return 1;
}

struct Object3dTransformationDetails
{

};

Matrix Identity={{1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}};
void RenderObject3d(Object3d * Object,Object3dTransformationDetails * TransformationDetails,GLuint ModelMatrixLocation, Matrix ParentMatrix=Identity)
{
    //TODO(Christof): Actually make use of TransformationDetails
    Matrix CurrentMatrix;
    SetTranslationMatrix(Object->Position.X,Object->Position.Y,Object->Position.Z,&CurrentMatrix);
    CurrentMatrix = CurrentMatrix * ParentMatrix;

    for(int i=0;i<Object->NumberOfChildren;i++)
    {
	RenderObject3d(&Object->Children[i],TransformationDetails,ModelMatrixLocation,CurrentMatrix);
    }
    UploadMatrix(&CurrentMatrix,ModelMatrixLocation);
    glBindVertexArray(Object->VertexBuffer);
    glDrawArrays(GL_TRIANGLES, 0, Object->NumTriangles*3);
    GLenum ErrorValue = glGetError();
    if(ErrorValue!=GL_NO_ERROR)
    {
	LogError("failed to render : %s",gluErrorString(ErrorValue));
    }
}

//TODO(Christof): Load Primitives from file to memory
//TODO(Christof): Generate Collision Meshes from Primitives?
//TODO(Christof): Generate Render Data from Primitives

/*TODO(Christof): Figure out if we can/need to use bindless textures or something similar for rendering, for now lets just go with the simple solution
 Probably just load all the textures into one big (1024x1024 or 2048x2048 - will need to check what size we need) texture and use offsets, since the textures are all quite small*/

int Count3DOChildren(char * Buffer,FILE_Object3dHeader * header)
{
    int NumChildren = 0;
    if(header->OffsetToChildObject)
    {
	NumChildren=1;
	header = (FILE_Object3dHeader *)(Buffer+header->OffsetToChildObject);
	while(header->OffsetToSiblingObject)
	{
	    header = (FILE_Object3dHeader *)(Buffer+header->OffsetToSiblingObject);
	    NumChildren++;
	}
    }
    return NumChildren;
}

const double TA_TO_GL_SCALE=1.0f/2500000.0f;

bool32 Load3DOFromBuffer(char * Buffer, Object3d * Object, int Offset=0)
{
    FILE_Object3dHeader * header = (FILE_Object3dHeader *)(Buffer+Offset);
    if(header->Version != 1)
    {
	LogError("Unknown Version in 3DO file: %d",header->Version);
	return 0;
    }
    if(header->OffsetToSiblingObject && !Offset)
    {
	LogError("Top Level 3DO Objects should not have siblings!");
	return 0;
    }

    int NameLength=strlen(Buffer + header->OffsetToObjectName)+1;
    Object->Name = (char *)malloc(NameLength);
    memcpy(Object->Name,Buffer+header->OffsetToObjectName,NameLength);
    LogDebug(Object->Name);
    Object->Position.X=header->XFromParent*TA_TO_GL_SCALE;
    Object->Position.Y=header->YFromParent*TA_TO_GL_SCALE;
    Object->Position.Z=header->ZFromParent*TA_TO_GL_SCALE;

    FILE_Object3dPrimitive * Primitives=(FILE_Object3dPrimitive*)(Buffer+header->OffsetToPrimitiveArray);
    FILE_Object3dPrimitive * CurrentPrimitive = Primitives;
    Object->NumberOfPrimitives = header->NumberOfPrimitives;
    Object->Primitives = (Object3dPrimitive *)malloc(sizeof(Object3dPrimitive)*Object->NumberOfPrimitives);
    for(int i=0;i<header->NumberOfPrimitives;i++)
    {
	if(CurrentPrimitive->OffsetToTextureName)
	{
	    Object->Primitives[i].Texture = GetTexture(Buffer+CurrentPrimitive->OffsetToTextureName,0);
	    if(!Object->Primitives[i].Texture)
	    {
		LogError("Could not get texture for primitive %d in %s, %s",i,Object->Name,Buffer+CurrentPrimitive->OffsetToTextureName);
	    }
	}
	else
	{
	    Object->Primitives[i].Texture=0;
	}
	Object->Primitives[i].NumberOfVertices = CurrentPrimitive->NumberOfVertexIndexes;
	Object->Primitives[i].VertexIndexes = (int *)malloc(sizeof(int)*Object->Primitives[i].NumberOfVertices);
	int16_t * VertexIndexes = (int16_t *)(Buffer + CurrentPrimitive->OffsetToVertexIndexArray);
	for(int j=0;j<Object->Primitives[i].NumberOfVertices;j++)
	    Object->Primitives[i].VertexIndexes[j]=VertexIndexes[j];

	Object->Primitives[i].ColorIndex = CurrentPrimitive->ColorIndex&0xFF;

	CurrentPrimitive++;
    }

    Object->NumberOfVertices = header->NumberOfVertexes;
    Object->Vertices = (float *)malloc(sizeof(float)*3*Object->NumberOfVertices);

    FILE_Object3dVertex * Vertices= (FILE_Object3dVertex *)(Buffer + header->OffsetToVertexArray);
    for(int i=0;i<Object->NumberOfVertices;i++)
    {
	Object->Vertices[i*3+0]=Vertices[i].x*TA_TO_GL_SCALE;
	Object->Vertices[i*3+1]=Vertices[i].y*TA_TO_GL_SCALE;
	Object->Vertices[i*3+2]=Vertices[i].z*TA_TO_GL_SCALE;
    }

    Object->NumberOfChildren = Count3DOChildren(Buffer,header);
    Object->Children = (Object3d *)malloc(sizeof(Object3d)*Object->NumberOfChildren);
    int ChildOffset=header->OffsetToChildObject;
    for(int i=0;i<Object->NumberOfChildren;i++)
    {
	Load3DOFromBuffer(Buffer, &(Object->Children[i]),ChildOffset);
	header = (FILE_Object3dHeader *)(Buffer+ChildOffset);
	ChildOffset=header->OffsetToSiblingObject;
    }

    return 1;
}

/**
   Frees all contents allocated by loading the object, leaving it in a state to be reused for loading without memory leaks
 **/
void Unload3DO(Object3d * Object)
{
    if(!Object)
	return;
    if(Object->Name)
	free(Object->Name);
    if(Object->Vertices)
	free(Object->Vertices);
    if(Object->Primitives)
    {
	for(int i=0;i<Object->NumberOfPrimitives;i++)
	    free(Object->Primitives[i].VertexIndexes);
	free(Object->Primitives);
    }
    for(int i=0;i<Object->NumberOfChildren;i++)
    {
	Unload3DO(&Object->Children[i]);
    }
    if(Object->Children)
	free(Object->Children);
}
<commit_msg>Fix color rendering<commit_after>

#pragma pack(push,1)
struct FILE_Object3dHeader
{
    int32_t Version;
    int32_t NumberOfVertexes;
    int32_t NumberOfPrimitives;
    int32_t OffsetToSelectionPrimitive;//Appears to be index into primitive array
    int32_t XFromParent;
    int32_t YFromParent;
    int32_t ZFromParent;
    int32_t OffsetToObjectName;
    int32_t Always_0;
    int32_t OffsetToVertexArray;
    int32_t OffsetToPrimitiveArray;
    int32_t OffsetToSiblingObject;
    int32_t OffsetToChildObject;
};

struct FILE_Object3dVertex
{
    int32_t x;
    int32_t y;
    int32_t z;
};

struct FILE_Object3dPrimitive
{
    int32_t ColorIndex;
    int32_t NumberOfVertexIndexes;
    int32_t Always_0;
    int32_t OffsetToVertexIndexArray;
    int32_t OffsetToTextureName;
    //Apparently Cavedog editor specific:
    int32_t Unknown_1;
    int32_t Unknown_2;
    int32_t Unknown_3;
};
#pragma pack(pop)

struct Position3d
{
    double X,Y,Z;
};

struct Object3d
{
    char * Name;
    Object3d * Children;
    int NumberOfChildren;
    Position3d Position;
    int NumberOfPrimitives;
    struct Object3dPrimitive * Primitives;
    int NumberOfVertices;
    GLfloat * Vertices;
    GLuint VertexBuffer;
    int NumTriangles;
};

struct Object3dPrimitive
{
    Texture * Texture;
    int NumberOfVertices;
    int ColorIndex;
    int * VertexIndexes;
};

void FillObject3dData(GLfloat * Data, int CurrentTriangle,int * VertexIndices,GLfloat * UV, Texture * Texture, Object3d * Object, Object3dPrimitive * Primitive)
{
    int Offset=CurrentTriangle*(3+2+3)*3;
    Data+=Offset;

    for(int i=0;i<3;i++)
    {
	Data[i*8+0]=Object->Vertices[Primitive->VertexIndexes[VertexIndices[i]]*3+0];
	Data[i*8+1]=Object->Vertices[Primitive->VertexIndexes[VertexIndices[i]]*3+1];
	Data[i*8+2]=Object->Vertices[Primitive->VertexIndexes[VertexIndices[i]]*3+2];

	Data[i*8+3]=Texture->U+Texture->Width*UV[i*2+0];
	Data[i*8+4]=Texture->V+Texture->Height*UV[i*2+1];

	Data[i*8+5]=(uint8_t)PaletteData[Primitive->ColorIndex*4+0]/255.0;
	Data[i*8+6]=(uint8_t)PaletteData[Primitive->ColorIndex*4+1]/255.0;
	Data[i*8+7]=(uint8_t)PaletteData[Primitive->ColorIndex*4+2]/255.0;
    }
}

Texture NoTexture={"",0,-2,-2,-1,-1,0};

bool32 PrepareObject3dForRendering(Object3d * Object)
{
    if(Object->VertexBuffer)
    {
	glDeleteVertexArrays(1,&Object->VertexBuffer);
    }

    Object->NumTriangles=0;
    for(int i=0;i<Object->NumberOfPrimitives;i++)
    {
	Object->NumTriangles += Object->Primitives[i].NumberOfVertices-2>0?Object->Primitives[i].NumberOfVertices-2:0;
    }
    GLfloat Data[Object->NumTriangles * (3+2+3)*3];//3 coord, 2 tex, 3 color
    //NOTE: signal no texture in some way, perhaps negative texture coords?
    int CurrentTriangle=0;
    for(int PrimitiveIndex=0;PrimitiveIndex<Object->NumberOfPrimitives;PrimitiveIndex++)
    {
	Object3dPrimitive * CurrentPrimitive=&Object->Primitives[PrimitiveIndex];
	Texture * Texture=CurrentPrimitive->Texture;
	if(!Texture)
	    Texture=&NoTexture;
	switch(CurrentPrimitive->NumberOfVertices)
	{
	case 1:
	case 2:
	    LogDebug("ignoring line or point (%d) in %s",CurrentPrimitive->NumberOfVertices,Object->Name);
	    break;
	case 3:
	{
	    GLfloat UVCoords[]={0,1, 1,1, 0,0};
	    int Vertexes[]={0,1,2};
	    FillObject3dData(Data,CurrentTriangle,Vertexes,UVCoords,Texture,Object,CurrentPrimitive);
	    CurrentTriangle++;
	}
	    break;
	case 4:
	{
	    GLfloat UVCoords1[]={1,0, 0,1, 1,1};
	    int Vertexes1[]={0,2,3};
	    FillObject3dData(Data,CurrentTriangle,Vertexes1,UVCoords1,Texture,Object,CurrentPrimitive);
	    CurrentTriangle++;
	    GLfloat UVCoords2[]={1,0, 0,0, 0,1};
	    int Vertexes2[]={0,1,2};
	    FillObject3dData(Data,CurrentTriangle,Vertexes2,UVCoords2,Texture,Object,CurrentPrimitive);
	    CurrentTriangle++;
	}
	    break;
	default:
	{
	    GLfloat UVCoords[6];
	    //Map sin/cos unit circle at (0,0) onto 1/2 unit circle at (0.5,0.5)
	    UVCoords[2*2]=0.5f*(1-(sin((2.0f*(CurrentPrimitive->NumberOfVertices-1)+1)*PI/float(CurrentPrimitive->NumberOfVertices))/cos(PI/CurrentPrimitive->NumberOfVertices)));
	    UVCoords[2*2+1]=0.5f*(1-(cos(PI/CurrentPrimitive->NumberOfVertices*(2.0f*(CurrentPrimitive->NumberOfVertices-1)+1))/cos(PI/CurrentPrimitive->NumberOfVertices)));

	    for(int i=0;i<CurrentPrimitive->NumberOfVertices-2;i++)
	    {
		int Vertexes[]={i,i+1,CurrentPrimitive->NumberOfVertices-1};

		for(int j=0;j<2;j++)
		{
		    //Map sin/cos unit circle at (0,0) onto 1/2 unit circle at (0.5,0.5)
		    UVCoords[j*2]=0.5f*(1-(sin((2.0f*(i+j)+1)*PI/float(CurrentPrimitive->NumberOfVertices))/cos(PI/CurrentPrimitive->NumberOfVertices)));
		    UVCoords[j*2+1]=0.5f*(1-(cos(PI/CurrentPrimitive->NumberOfVertices*(2.0f*(i+j)+1))/cos(PI/CurrentPrimitive->NumberOfVertices)));
		}
		FillObject3dData(Data,CurrentTriangle,Vertexes,UVCoords,Texture,Object,CurrentPrimitive);
		CurrentTriangle++;
	    }
	}
	    break;
	}
    }

    glGenVertexArrays(1,&Object->VertexBuffer);
    glBindVertexArray(Object->VertexBuffer);

    GLuint VertexBuffer;
    glGenBuffers(1,&VertexBuffer);

    glBindBuffer(GL_ARRAY_BUFFER,VertexBuffer);
    glBufferData(GL_ARRAY_BUFFER,sizeof(GLfloat)*Object->NumTriangles*(3+2+3)*3,Data,GL_STATIC_DRAW);
    glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,sizeof(GLfloat)*(3+2+3),0);
    glVertexAttribPointer(1,2,GL_FLOAT,GL_FALSE,sizeof(GLfloat)*(3+2+3),(GLvoid*)(sizeof(GLfloat)*3));

    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);

    glVertexAttribPointer(2,3,GL_FLOAT,GL_FALSE,sizeof(GLfloat)*(3+2+3),(GLvoid*)(sizeof(GLfloat)*5));
    glEnableVertexAttribArray(2);

    glBindVertexArray(0);
    //glDeleteBuffers(1,&VertexBuffer);

    for(int i=0;i<Object->NumberOfChildren;i++)
    {
	if(!PrepareObject3dForRendering(&Object->Children[i]))
	    return 0;
    }

    return 1;
}

struct Object3dTransformationDetails
{

};

Matrix Identity={{1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}};
void RenderObject3d(Object3d * Object,Object3dTransformationDetails * TransformationDetails,GLuint ModelMatrixLocation, Matrix ParentMatrix=Identity)
{
    //TODO(Christof): Actually make use of TransformationDetails
    Matrix CurrentMatrix;
    SetTranslationMatrix(Object->Position.X,Object->Position.Y,Object->Position.Z,&CurrentMatrix);
    CurrentMatrix = CurrentMatrix * ParentMatrix;

    for(int i=0;i<Object->NumberOfChildren;i++)
    {
	RenderObject3d(&Object->Children[i],TransformationDetails,ModelMatrixLocation,CurrentMatrix);
    }
    UploadMatrix(&CurrentMatrix,ModelMatrixLocation);
    glBindVertexArray(Object->VertexBuffer);
    glDrawArrays(GL_TRIANGLES, 0, Object->NumTriangles*3);
    GLenum ErrorValue = glGetError();
    if(ErrorValue!=GL_NO_ERROR)
    {
	LogError("failed to render : %s",gluErrorString(ErrorValue));
    }
}

//TODO(Christof): Load Primitives from file to memory
//TODO(Christof): Generate Collision Meshes from Primitives?
//TODO(Christof): Generate Render Data from Primitives

/*TODO(Christof): Figure out if we can/need to use bindless textures or something similar for rendering, for now lets just go with the simple solution
 Probably just load all the textures into one big (1024x1024 or 2048x2048 - will need to check what size we need) texture and use offsets, since the textures are all quite small*/

int Count3DOChildren(char * Buffer,FILE_Object3dHeader * header)
{
    int NumChildren = 0;
    if(header->OffsetToChildObject)
    {
	NumChildren=1;
	header = (FILE_Object3dHeader *)(Buffer+header->OffsetToChildObject);
	while(header->OffsetToSiblingObject)
	{
	    header = (FILE_Object3dHeader *)(Buffer+header->OffsetToSiblingObject);
	    NumChildren++;
	}
    }
    return NumChildren;
}

const double TA_TO_GL_SCALE=1.0f/2500000.0f;

bool32 Load3DOFromBuffer(char * Buffer, Object3d * Object, int Offset=0)
{
    FILE_Object3dHeader * header = (FILE_Object3dHeader *)(Buffer+Offset);
    if(header->Version != 1)
    {
	LogError("Unknown Version in 3DO file: %d",header->Version);
	return 0;
    }
    if(header->OffsetToSiblingObject && !Offset)
    {
	LogError("Top Level 3DO Objects should not have siblings!");
	return 0;
    }

    int NameLength=strlen(Buffer + header->OffsetToObjectName)+1;
    Object->Name = (char *)malloc(NameLength);
    memcpy(Object->Name,Buffer+header->OffsetToObjectName,NameLength);
    Object->Position.X=header->XFromParent*TA_TO_GL_SCALE;
    Object->Position.Y=header->YFromParent*TA_TO_GL_SCALE;
    Object->Position.Z=header->ZFromParent*TA_TO_GL_SCALE;

    FILE_Object3dPrimitive * Primitives=(FILE_Object3dPrimitive*)(Buffer+header->OffsetToPrimitiveArray);
    FILE_Object3dPrimitive * CurrentPrimitive = Primitives;
    Object->NumberOfPrimitives = header->NumberOfPrimitives;
    Object->Primitives = (Object3dPrimitive *)malloc(sizeof(Object3dPrimitive)*Object->NumberOfPrimitives);
    for(int i=0;i<header->NumberOfPrimitives;i++)
    {
	if(CurrentPrimitive->OffsetToTextureName)
	{
	    Object->Primitives[i].Texture = GetTexture(Buffer+CurrentPrimitive->OffsetToTextureName,0);
	    if(!Object->Primitives[i].Texture)
	    {
		LogError("Could not get texture for primitive %d in %s, %s",i,Object->Name,Buffer+CurrentPrimitive->OffsetToTextureName);
	    }
	}
	else
	{
	    Object->Primitives[i].Texture=0;
	}
	Object->Primitives[i].NumberOfVertices = CurrentPrimitive->NumberOfVertexIndexes;
	Object->Primitives[i].VertexIndexes = (int *)malloc(sizeof(int)*Object->Primitives[i].NumberOfVertices);
	int16_t * VertexIndexes = (int16_t *)(Buffer + CurrentPrimitive->OffsetToVertexIndexArray);
	for(int j=0;j<Object->Primitives[i].NumberOfVertices;j++)
	    Object->Primitives[i].VertexIndexes[j]=VertexIndexes[j];

	Object->Primitives[i].ColorIndex = CurrentPrimitive->ColorIndex & 255;

	CurrentPrimitive++;
    }

    Object->NumberOfVertices = header->NumberOfVertexes;
    Object->Vertices = (float *)malloc(sizeof(float)*3*Object->NumberOfVertices);

    FILE_Object3dVertex * Vertices= (FILE_Object3dVertex *)(Buffer + header->OffsetToVertexArray);
    for(int i=0;i<Object->NumberOfVertices;i++)
    {
	Object->Vertices[i*3+0]=Vertices[i].x*TA_TO_GL_SCALE;
	Object->Vertices[i*3+1]=Vertices[i].y*TA_TO_GL_SCALE;
	Object->Vertices[i*3+2]=Vertices[i].z*TA_TO_GL_SCALE;
    }

    Object->NumberOfChildren = Count3DOChildren(Buffer,header);
    Object->Children = (Object3d *)malloc(sizeof(Object3d)*Object->NumberOfChildren);
    int ChildOffset=header->OffsetToChildObject;
    for(int i=0;i<Object->NumberOfChildren;i++)
    {
	Load3DOFromBuffer(Buffer, &(Object->Children[i]),ChildOffset);
	header = (FILE_Object3dHeader *)(Buffer+ChildOffset);
	ChildOffset=header->OffsetToSiblingObject;
    }

    return 1;
}

/**
   Frees all contents allocated by loading the object, leaving it in a state to be reused for loading without memory leaks
 **/
void Unload3DO(Object3d * Object)
{
    if(!Object)
	return;
    if(Object->Name)
	free(Object->Name);
    if(Object->Vertices)
	free(Object->Vertices);
    if(Object->Primitives)
    {
	for(int i=0;i<Object->NumberOfPrimitives;i++)
	    free(Object->Primitives[i].VertexIndexes);
	free(Object->Primitives);
    }
    for(int i=0;i<Object->NumberOfChildren;i++)
    {
	Unload3DO(&Object->Children[i]);
    }
    if(Object->Children)
	free(Object->Children);
}
<|endoftext|>


<commit_before>class Solution {
public:
    /**
     * @param digits a number represented as an array of digits
     * @return the result
     */
    vector<int> plusOne(vector<int>& digits) {
        // Write your code here
        int i,j,k,n=digits.size();
        int tmp,s_tmp,jw=0;
        std::vector<int> vRev(digits.rbegin(),digits.rend());
        for (auto &s:vRev){
        	cout<<s<<" ";
        	s_tmp=jw+s+1;
        	s=s_tmp%10;
        	cout<<s<<";";
        	jw=s_tmp/10;
        }
        if (jw>1) vRev.push_back(jw);

        std::vector<int> rt_v(vRev.rbegin(),vRev.rend());
        return rt_v;
    }
};<commit_msg>Submit again<commit_after>class Solution {
public:
    /**
     * @param digits a number represented as an array of digits
     * @return the result
     */
    vector<int> plusOne(vector<int>& digits) {
        // Write your code here
        int i,j,k,n=digits.size();
        int tmp,s_tmp,jw=0;
        std::vector<int> vRev(digits.rbegin(),digits.rend());
        for (auto &s:vRev){
        	// cout<<s<<" ";
        	s_tmp=jw+s+1;
        	s=s_tmp%10;
        	// cout<<s<<";";
        	jw=s_tmp/10;
        	// cout<<jw;
        }
        if (jw>=1) vRev.push_back(jw);

        std::vector<int> rt_v(vRev.rbegin(),vRev.rend());
        return rt_v;
    }
};<|endoftext|>


<commit_before>class Solution {
public:
    /**
     * @param s A string
     * @return whether the string is a valid parentheses
     */
    bool isValidParentheses(string& s) {
        // Write your code here
    }
};<commit_msg>solving 423<commit_after>class Solution {
public:
    /**
     * @param s A string
     * @return whether the string is a valid parentheses
     */

    deque<int> que1;
    map<char,int> baseOfPar;
    bool isValidParentheses(string& s) {
        // Write your code here

        //init
        int i,j,k,l_s=s.size();
        string s_tem=s;

        baseOfPar['(']=1;        baseOfPar[')']=4;
        baseOfPar['[']=2;        baseOfPar[']']=5;
        baseOfPar['{']=3;        baseOfPar['}']=6;

        //loop
        for (i=0;i<l_s;i++){
        	if
        }
    }

};<|endoftext|>


<commit_before><commit_msg>Use OpenSSL return values for client_hello_cb<commit_after><|endoftext|>