<commit_before>//=======================================================================
// Copyright (c) 2014-2020 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#pragma once

namespace etl {

/*!
 * \brief Unary operation sampling with a Bernoulli distribution
 * \tparam T The type of value
 */
template <typename T>
struct bernoulli_unary_op {
    static constexpr bool linear      = true;  ///< Indicates if the operator is linear
    static constexpr bool thread_safe = false; ///< Indicates if the operator is thread safe or not

    /*!
     * \brief Indicates if the expression is vectorizable using the
     * given vector mode
     * \tparam V The vector mode
     */
    template <vector_mode_t V>
    static constexpr bool vectorizable = false;

    /*!
     * \brief Indicates if the operator can be computed on GPU
     */
    template <typename E>
    static constexpr bool gpu_computable = false;

    /*!
     * \brief Apply the unary operator on x
     * \param x The value on which to apply the operator
     * \return The result of applying the unary operator on x
     */
    static T apply(const T& x) {
        static random_engine rand_engine(std::time(nullptr));
        static std::uniform_real_distribution<double> distribution(0.0, 1.0);

        return x > distribution(rand_engine) ? 1.0 : 0.0;
    }

    /*!
     * \brief Returns a textual representation of the operator
     * \return a string representing the operator
     */
    static std::string desc() noexcept {
        return "bernoulli";
    }
};

/*!
 * \brief Unary operation sampling with a Bernoulli distribution
 * \tparam T The type of value
 */
template <typename G, typename T>
struct bernoulli_unary_g_op {
    static constexpr bool linear      = true;  ///< Indicates if the operator is linear
    static constexpr bool thread_safe = false; ///< Indicates if the operator is thread safe or not

private:
    G& rand_engine; ///< The custom random engine

public:
    /*!
     * \brief Construct a new bernoulli_unary_g_op
     */
    explicit bernoulli_unary_g_op(G& rand_engine) : rand_engine(rand_engine) {
        //Nothing else to init
    }

    /*!
     * \brief Indicates if the expression is vectorizable using the
     * given vector mode
     * \tparam V The vector mode
     */
    template <vector_mode_t V>
    static constexpr bool vectorizable = false;

    /*!
     * \brief Indicates if the operator can be computed on GPU
     */
    template <typename E>
    static constexpr bool gpu_computable = false;

    /*!
     * \brief Apply the unary operator on x
     * \param x The value on which to apply the operator
     * \return The result of applying the unary operator on x
     */
    T apply(const T& x) const {
        std::uniform_real_distribution<double> distribution(0.0, 1.0);

        return x > distribution(rand_engine) ? 1.0 : 0.0;
    }

    /*!
     * \brief Returns a textual representation of the operator
     * \return a string representing the operator
     */
    static std::string desc() noexcept {
        return "bernoulli";
    }
};

/*!
 * \brief Unary operation sampling with a reverse Bernoulli distribution
 * \tparam T The type of value
 */
template <typename T>
struct reverse_bernoulli_unary_op {
    static constexpr bool linear      = true;  ///< Indicates if the operator is linear
    static constexpr bool thread_safe = false; ///< Indicates if the operator is thread safe or not

    /*!
     * \brief Indicates if the expression is vectorizable using the
     * given vector mode
     * \tparam V The vector mode
     */
    template <vector_mode_t V>
    static constexpr bool vectorizable = false;

    /*!
     * \brief Indicates if the operator can be computed on GPU
     */
    template <typename E>
    static constexpr bool gpu_computable = false;

    /*!
     * \brief Apply the unary operator on x
     * \param x The value on which to apply the operator
     * \return The result of applying the unary operator on x
     */
    static T apply(const T& x) {
        static random_engine rand_engine(std::time(nullptr));
        static std::uniform_real_distribution<double> distribution(0.0, 1.0);

        return x > distribution(rand_engine) ? 0.0 : 1.0;
    }

    /*!
     * \brief Returns a textual representation of the operator
     * \return a string representing the operator
     */
    static std::string desc() noexcept {
        return "bernoulli_reverse";
    }
};

/*!
 * \brief Unary operation sampling with a reverse Bernoulli distribution
 * \tparam T The type of value
 */
template <typename G, typename T>
struct reverse_bernoulli_unary_g_op {
    static constexpr bool linear      = true;  ///< Indicates if the operator is linear
    static constexpr bool thread_safe = false; ///< Indicates if the operator is thread safe or not

private:
    G& rand_engine; ///< The custom random engine

public:
    /*!
     * \brief Construct a new reverse_bernoulli_unary_g_op
     */
    explicit reverse_bernoulli_unary_g_op(G& rand_engine) : rand_engine(rand_engine) {
        //Nothing else to init
    }

    /*!
     * \brief Indicates if the expression is vectorizable using the
     * given vector mode
     * \tparam V The vector mode
     */
    template <vector_mode_t V>
    static constexpr bool vectorizable = false;

    /*!
     * \brief Indicates if the operator can be computed on GPU
     */
    template <typename E>
    static constexpr bool gpu_computable = false;

    /*!
     * \brief Apply the unary operator on x
     * \param x The value on which to apply the operator
     * \return The result of applying the unary operator on x
     */
    T apply(const T& x) const {
        std::uniform_real_distribution<double> distribution(0.0, 1.0);

        return x > distribution(rand_engine) ? 0.0 : 1.0;
    }

    /*!
     * \brief Returns a textual representation of the operator
     * \return a string representing the operator
     */
    static std::string desc() noexcept {
        return "bernoulli_reverse";
    }
};

} //end of namespace etl
<commit_msg>GPU Support for bernoulli sampling<commit_after>//=======================================================================
// Copyright (c) 2014-2020 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#pragma once

#include "etl/impl/egblas/bernoulli.hpp"

namespace etl {

/*!
 * \brief Unary operation sampling with a Bernoulli distribution
 * \tparam T The type of value
 */
template <typename T>
struct bernoulli_unary_op {
    static constexpr bool linear      = true;  ///< Indicates if the operator is linear
    static constexpr bool thread_safe = false; ///< Indicates if the operator is thread safe or not

    /*!
     * \brief Indicates if the expression is vectorizable using the
     * given vector mode
     * \tparam V The vector mode
     */
    template <vector_mode_t V>
    static constexpr bool vectorizable = false;

    /*!
     * \brief Indicates if the operator can be computed on GPU
     */
    template <typename E>
    static constexpr bool gpu_computable = (is_single_precision_t<T> && impl::egblas::has_sbernoulli_sample_seed)
                                           || (is_double_precision_t<T> && impl::egblas::has_dbernoulli_sample_seed);

    /*!
     * \brief Apply the unary operator on x
     * \param x The value on which to apply the operator
     * \return The result of applying the unary operator on x
     */
    static T apply(const T& x) {
        static random_engine rand_engine(std::time(nullptr));
        static std::uniform_real_distribution<double> distribution(0.0, 1.0);

        return x > distribution(rand_engine) ? 1.0 : 0.0;
    }

    /*!
     * \brief Compute the result of the operation using the GPU
     *
     * \param x The expression of the unary operation
     *
     * \return The result of applying the unary operator on x. The result must be a GPU computed expression.
     */
    template <typename X, typename Y>
    static auto gpu_compute_hint(const X & x, Y& y) noexcept {
        static random_engine rand_engine(std::time(nullptr));

        std::uniform_int_distribution<long> seed_dist;

        decltype(auto) t1 = smart_gpu_compute_hint(x, y);

        auto t2 = force_temporary_gpu_dim_only(t1);

        T alpha(1);
        impl::egblas::bernoulli_sample_seed(etl::size(y), alpha, t1.gpu_memory(), 1, t2.gpu_memory(), 1, seed_dist(rand_engine));

        return t2;
    }

    /*!
     * \brief Compute the result of the operation using the GPU
     *
     * \param x The expression of the unary operation
     * \param y The expression into which to store the reuslt
     */
    template <typename X, typename Y>
    static Y& gpu_compute(const X & x, Y& y) noexcept {
        static random_engine rand_engine(std::time(nullptr));

        std::uniform_int_distribution<long> seed_dist;

        decltype(auto) t1 = select_smart_gpu_compute(x, y);

        T alpha(1);
        impl::egblas::bernoulli_sample_seed(etl::size(y), alpha, t1.gpu_memory(), 1, y.gpu_memory(), 1, seed_dist(rand_engine));

        y.validate_gpu();
        y.invalidate_cpu();

        return y;
    }

    /*!
     * \brief Returns a textual representation of the operator
     * \return a string representing the operator
     */
    static std::string desc() noexcept {
        return "bernoulli";
    }
};

/*!
 * \brief Unary operation sampling with a Bernoulli distribution
 * \tparam T The type of value
 */
template <typename G, typename T>
struct bernoulli_unary_g_op {
    static constexpr bool linear      = true;  ///< Indicates if the operator is linear
    static constexpr bool thread_safe = false; ///< Indicates if the operator is thread safe or not

private:
    G& rand_engine; ///< The custom random engine

public:
    /*!
     * \brief Construct a new bernoulli_unary_g_op
     */
    explicit bernoulli_unary_g_op(G& rand_engine) : rand_engine(rand_engine) {
        //Nothing else to init
    }

    /*!
     * \brief Indicates if the expression is vectorizable using the
     * given vector mode
     * \tparam V The vector mode
     */
    template <vector_mode_t V>
    static constexpr bool vectorizable = false;

    /*!
     * \brief Indicates if the operator can be computed on GPU
     */
    template <typename E>
    static constexpr bool gpu_computable = (is_single_precision_t<T> && impl::egblas::has_sbernoulli_sample_seed)
                                           || (is_double_precision_t<T> && impl::egblas::has_dbernoulli_sample_seed);

    /*!
     * \brief Apply the unary operator on x
     * \param x The value on which to apply the operator
     * \return The result of applying the unary operator on x
     */
    T apply(const T& x) const {
        std::uniform_real_distribution<double> distribution(0.0, 1.0);

        return x > distribution(rand_engine) ? 1.0 : 0.0;
    }

    /*!
     * \brief Compute the result of the operation using the GPU
     *
     * \param x The expression of the unary operation
     *
     * \return The result of applying the unary operator on x. The result must be a GPU computed expression.
     */
    template <typename X, typename Y>
    auto gpu_compute_hint(const X & x, Y& y) const noexcept {
        std::uniform_int_distribution<long> seed_dist;

        decltype(auto) t1 = smart_gpu_compute_hint(x, y);

        auto t2 = force_temporary_gpu_dim_only(t1);

        T alpha(1);
        impl::egblas::bernoulli_sample_seed(etl::size(y), alpha, t1.gpu_memory(), 1, t2.gpu_memory(), 1, seed_dist(rand_engine));

        return t2;
    }

    /*!
     * \brief Compute the result of the operation using the GPU
     *
     * \param x The expression of the unary operation
     * \param y The expression into which to store the reuslt
     */
    template <typename X, typename Y>
    Y& gpu_compute(const X & x, Y& y) const noexcept {
        std::uniform_int_distribution<long> seed_dist;

        decltype(auto) t1 = select_smart_gpu_compute(x, y);

        T alpha(1);
        impl::egblas::bernoulli_sample_seed(etl::size(y), alpha, t1.gpu_memory(), 1, y.gpu_memory(), 1, seed_dist(rand_engine));

        y.validate_gpu();
        y.invalidate_cpu();

        return y;
    }

    /*!
     * \brief Returns a textual representation of the operator
     * \return a string representing the operator
     */
    static std::string desc() noexcept {
        return "bernoulli";
    }
};

/*!
 * \brief Unary operation sampling with a reverse Bernoulli distribution
 * \tparam T The type of value
 */
template <typename T>
struct reverse_bernoulli_unary_op {
    static constexpr bool linear      = true;  ///< Indicates if the operator is linear
    static constexpr bool thread_safe = false; ///< Indicates if the operator is thread safe or not

    /*!
     * \brief Indicates if the expression is vectorizable using the
     * given vector mode
     * \tparam V The vector mode
     */
    template <vector_mode_t V>
    static constexpr bool vectorizable = false;

    /*!
     * \brief Indicates if the operator can be computed on GPU
     */
    template <typename E>
    static constexpr bool gpu_computable = false;

    /*!
     * \brief Apply the unary operator on x
     * \param x The value on which to apply the operator
     * \return The result of applying the unary operator on x
     */
    static T apply(const T& x) {
        static random_engine rand_engine(std::time(nullptr));
        static std::uniform_real_distribution<double> distribution(0.0, 1.0);

        return x > distribution(rand_engine) ? 0.0 : 1.0;
    }

    /*!
     * \brief Returns a textual representation of the operator
     * \return a string representing the operator
     */
    static std::string desc() noexcept {
        return "bernoulli_reverse";
    }
};

/*!
 * \brief Unary operation sampling with a reverse Bernoulli distribution
 * \tparam T The type of value
 */
template <typename G, typename T>
struct reverse_bernoulli_unary_g_op {
    static constexpr bool linear      = true;  ///< Indicates if the operator is linear
    static constexpr bool thread_safe = false; ///< Indicates if the operator is thread safe or not

private:
    G& rand_engine; ///< The custom random engine

public:
    /*!
     * \brief Construct a new reverse_bernoulli_unary_g_op
     */
    explicit reverse_bernoulli_unary_g_op(G& rand_engine) : rand_engine(rand_engine) {
        //Nothing else to init
    }

    /*!
     * \brief Indicates if the expression is vectorizable using the
     * given vector mode
     * \tparam V The vector mode
     */
    template <vector_mode_t V>
    static constexpr bool vectorizable = false;

    /*!
     * \brief Indicates if the operator can be computed on GPU
     */
    template <typename E>
    static constexpr bool gpu_computable = false;

    /*!
     * \brief Apply the unary operator on x
     * \param x The value on which to apply the operator
     * \return The result of applying the unary operator on x
     */
    T apply(const T& x) const {
        std::uniform_real_distribution<double> distribution(0.0, 1.0);

        return x > distribution(rand_engine) ? 0.0 : 1.0;
    }

    /*!
     * \brief Returns a textual representation of the operator
     * \return a string representing the operator
     */
    static std::string desc() noexcept {
        return "bernoulli_reverse";
    }
};

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


<commit_before><commit_msg>replace com::sun::star with css in chart ooxml export<commit_after><|endoftext|>


<commit_before>/* ************************************************************************* */
/* This file is part of Shard.                                               */
/*                                                                           */
/* Shard is free software: you can redistribute it and/or modify             */
/* it under the terms of the GNU Affero General Public License as            */
/* published by the Free Software Foundation.                                */
/*                                                                           */
/* This program is distributed in the hope that it will be useful,           */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the              */
/* GNU Affero General Public License for more details.                       */
/*                                                                           */
/* You should have received a copy of the GNU Affero General Public License  */
/* along with this program. If not, see <http://www.gnu.org/licenses/>.      */
/* ************************************************************************* */

#pragma once

/* ************************************************************************* */

#include <fstream>

// Shard
#include "shard/Path.hpp"
#include "shard/String.hpp"
#include "shard/ViewPtr.hpp"
#include "shard/UniquePtr.hpp"
#include "shard/SourceLocation.hpp"

/* ************************************************************************* */

namespace shard {
inline namespace v1 {
namespace tokenizer {

/* ************************************************************************* */

using ReadMode = char;

/* ************************************************************************* */

class Source; //FWD declaration

/* ************************************************************************* */

/**
 * @brief Input iterator from Source.
 */
class SourceIterator
{

protected:

    ViewPtr<Source> m_source;

public:

    /**
     * @brief constructs empty SourceIterator.
     */
    SourceIterator() = default;

    /**
     * @brief constructs SourceIterator for given Source.
     */
    explicit SourceIterator(ViewPtr<Source> source):
        m_source(source) {}

    inline int operator*() const;
    inline SourceIterator& operator++();
    inline SourceIterator operator++(int);

    /**
     * @brief returns pointer to related Source.
     */
    inline ViewPtr<Source> getSource() const noexcept
    {
        return m_source;
    }
};

/* ************************************************************************* */

inline bool operator==(const SourceIterator& lhs, const SourceIterator& rhs)
{
    return (lhs.getSource() == nullptr || (*lhs) == std::char_traits<ReadMode>::eof())
        && (rhs.getSource() == nullptr || (*rhs) == std::char_traits<ReadMode>::eof());
}

inline bool operator!=(const SourceIterator& lhs, const SourceIterator& rhs)
{
    return !(lhs == rhs);
}

/* ************************************************************************* */

/**
 * @brief Streams data from various types of input.
 */
class Source
{

protected:

    UniquePtr<std::basic_streambuf<ReadMode>> m_sb;
    SourceLocation m_loc;

/* ************************************************************************* */

public:

    /**
     * @brief constructs Source with input from file.
     */
    explicit Source (const Path& path):
            m_sb([](const auto& l_path)
            {
                auto ptr = makeUnique<std::basic_filebuf<ReadMode>>();
                ptr->open(l_path, std::ios_base::in | std::ios_base::binary);
                return ptr;
            }(path)),
            m_loc(SourceLocation(1, 1)) {}

    /**
     * @brief constructs Source with input from string.
     */
    explicit Source (const String& source):
            m_sb(makeUnique<std::basic_stringbuf<ReadMode>>(source)),
            m_loc(SourceLocation(1, 1)) {}

/* ************************************************************************* */

protected:

    inline void incrLoc()
    {
        auto temp = get();
        if (temp == '\n' || temp == '\r')
        {
            m_loc.addLine();
        }
        else
        {
            m_loc.addColumn();
        }
    }

/* ************************************************************************* */

public:

    /**
     * @brief returns if input is empty.
     */
    inline bool empty() const
    {
        return get() == std::char_traits<ReadMode>::eof();
        //return m_sb->in_avail() <= 0;
    }

    /**
     * @brief read current character.
     */
    inline int get() const
    {
        return m_sb->sgetc();
    }

    /**
     * @brief read current character and move to next.
     */
    inline int extract()
    {
        incrLoc();
        return m_sb->sbumpc();
    }

    /**
     * @brief move to next character and read it.
     */
    inline int getNext()
    {
        incrLoc();
        return m_sb->snextc();
    }

    /**
     * @brief discard current character and move to next.
     */
    inline void toss()
    {
        incrLoc();
        m_sb->sbumpc();
    }

    /* ************************************************************************* */

public:

    inline const SourceLocation& getLocation() const noexcept
    {
        return m_loc;
    }

    /* ************************************************************************* */

public:

    /**
     * @brief returns tokenizer iterator pointing to currect token.
     */
    inline SourceIterator begin() noexcept
    {
        return SourceIterator(this);
    }

    /**
     * @brief returns tokenizer iterator pointing to token with end.
     */
    inline SourceIterator end() noexcept
    {
        return SourceIterator(nullptr);
    }
};

/* ************************************************************************* */

inline int SourceIterator::operator*() const
{
    return m_source->get();
}

inline SourceIterator& SourceIterator::operator++()
{
    m_source->extract();
    return *this;
}

inline SourceIterator SourceIterator::operator++(int)
{
    SourceIterator tmp(*this);
    operator++();
    return tmp;
}

/* ************************************************************************* */

}
}
}

/* ************************************************************************* */
<commit_msg>removed location from source<commit_after>/* ************************************************************************* */
/* This file is part of Shard.                                               */
/*                                                                           */
/* Shard is free software: you can redistribute it and/or modify             */
/* it under the terms of the GNU Affero General Public License as            */
/* published by the Free Software Foundation.                                */
/*                                                                           */
/* This program is distributed in the hope that it will be useful,           */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the              */
/* GNU Affero General Public License for more details.                       */
/*                                                                           */
/* You should have received a copy of the GNU Affero General Public License  */
/* along with this program. If not, see <http://www.gnu.org/licenses/>.      */
/* ************************************************************************* */

#pragma once

/* ************************************************************************* */

#include <fstream>

// Shard
#include "shard/Path.hpp"
#include "shard/String.hpp"
#include "shard/ViewPtr.hpp"
#include "shard/UniquePtr.hpp"

/* ************************************************************************* */

namespace shard {
inline namespace v1 {
namespace tokenizer {

/* ************************************************************************* */

using ReadMode = char;

/* ************************************************************************* */

class Source; //FWD declaration

/* ************************************************************************* */

/**
 * @brief Input iterator from Source.
 */
class SourceIterator
{

protected:

    ViewPtr<Source> m_source;

public:

    /**
     * @brief constructs empty SourceIterator.
     */
    SourceIterator() = default;

    /**
     * @brief constructs SourceIterator for given Source.
     */
    explicit SourceIterator(ViewPtr<Source> source):
        m_source(source) {}

    inline int operator*() const;
    inline SourceIterator& operator++();
    inline SourceIterator operator++(int);

    /**
     * @brief returns pointer to related Source.
     */
    inline ViewPtr<Source> getSource() const noexcept
    {
        return m_source;
    }
};

/* ************************************************************************* */

inline bool operator==(const SourceIterator& lhs, const SourceIterator& rhs)
{
    return (lhs.getSource() == nullptr || (*lhs) == std::char_traits<ReadMode>::eof())
        && (rhs.getSource() == nullptr || (*rhs) == std::char_traits<ReadMode>::eof());
}

inline bool operator!=(const SourceIterator& lhs, const SourceIterator& rhs)
{
    return !(lhs == rhs);
}

/* ************************************************************************* */

/**
 * @brief Streams data from various types of input.
 */
class Source
{

protected:

    UniquePtr<std::basic_streambuf<ReadMode>> m_sb;

/* ************************************************************************* */

public:

    /**
     * @brief constructs Source with input from file.
     */
    explicit Source (const Path& path):
            m_sb([](const auto& l_path)
            {
                auto ptr = makeUnique<std::basic_filebuf<ReadMode>>();
                ptr->open(l_path, std::ios_base::in | std::ios_base::binary);
                return ptr;
            }(path)) {}

    /**
     * @brief constructs Source with input from string.
     */
    explicit Source (const String& source):
            m_sb(makeUnique<std::basic_stringbuf<ReadMode>>(source)) {}

/* ************************************************************************* */

public:

    /**
     * @brief returns if input is empty.
     */
    inline bool empty() const
    {
        return get() == std::char_traits<ReadMode>::eof();
        //return m_sb->in_avail() <= 0;
    }

    /**
     * @brief read current character.
     */
    inline int get() const
    {
        return m_sb->sgetc();
    }

    /**
     * @brief read current character and move to next.
     */
    inline int extract() const
    {
        return m_sb->sbumpc();
    }

    /**
     * @brief move to next character and read it.
     */
    inline int getNext() const
    {
        return m_sb->snextc();
    }

    /**
     * @brief discard current character and move to next.
     */
    inline void toss() const
    {
        m_sb->sbumpc();
    }

    /* ************************************************************************* */

public:

    /**
     * @brief returns tokenizer iterator pointing to currect token.
     */
    inline SourceIterator begin() noexcept
    {
        return SourceIterator(this);
    }

    /**
     * @brief returns tokenizer iterator pointing to token with end.
     */
    inline SourceIterator end() noexcept
    {
        return SourceIterator(nullptr);
    }
};

/* ************************************************************************* */

inline int SourceIterator::operator*() const
{
    return m_source->get();
}

inline SourceIterator& SourceIterator::operator++()
{
    m_source->extract();
    return *this;
}

inline SourceIterator SourceIterator::operator++(int)
{
    SourceIterator tmp(*this);
    operator++();
    return tmp;
}

/* ************************************************************************* */

}
}
}

/* ************************************************************************* */
<|endoftext|>


<commit_before>/* ************************************************************************* */
/* This file is part of Shard.                                               */
/*                                                                           */
/* Shard is free software: you can redistribute it and/or modify             */
/* it under the terms of the GNU Affero General Public License as            */
/* published by the Free Software Foundation.                                */
/*                                                                           */
/* This program is distributed in the hope that it will be useful,           */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the              */
/* GNU Affero General Public License for more details.                       */
/*                                                                           */
/* You should have received a copy of the GNU Affero General Public License  */
/* along with this program. If not, see <http://www.gnu.org/licenses/>.      */
/* ************************************************************************* */

#pragma once

/* ************************************************************************* */

#include <fstream>

// Shard
#include "shard/Path.hpp"
#include "shard/String.hpp"
#include "shard/ViewPtr.hpp"
#include "shard/UniquePtr.hpp"

/* ************************************************************************* */

namespace shard {
inline namespace v1 {
namespace tokenizer {

/* ************************************************************************* */

using ReadMode = char;

/* ************************************************************************* */

class Source; //FWD declaration

/* ************************************************************************* */

class SourceIterator
{

protected:

    ViewPtr<Source> m_source;

public:

    /**
     * @brief constructs empty SourceIterator.
     */
    SourceIterator() = default;

    /**
     * @brief constructs SourceIterator for given Source.
     */
    explicit SourceIterator(ViewPtr<Source> source):
        m_source(source) {}

    inline ReadMode operator*() const;
    inline SourceIterator& operator++();
    inline SourceIterator operator++(int);

    /**
     * @brief returns pointer to related Source.
     */
    inline ViewPtr<Source> getSource() const noexcept
    {
        return m_source;
    }
};

/* ************************************************************************* */

inline bool operator==(const SourceIterator& lhs, const SourceIterator& rhs)
{
    return (lhs.getSource() == nullptr || (*lhs) == std::char_traits<ReadMode>::eof())
        && (rhs.getSource() == nullptr || (*rhs) == std::char_traits<ReadMode>::eof());
}

inline bool operator!=(const SourceIterator& lhs, const SourceIterator& rhs)
{
    return !(lhs == rhs);
}

/* ************************************************************************* */

class Source
{

protected:

    UniquePtr<std::basic_streambuf<ReadMode>> m_sb;

public:

    /**
     * @brief constructs Source with input from file.
     */
    explicit Source (const Path& path):
            m_sb([](const auto& l_path)
            {
                auto ptr = makeUnique<std::basic_filebuf<ReadMode>>();
                ptr->open(l_path, std::ios_base::in | std::ios_base::binary);
                return ptr;
            }(path)) {}

    /**
     * @brief constructs Source with input from string.
     */
    explicit Source (const String& source):
            m_sb(makeUnique<std::basic_stringbuf<ReadMode>>(source)) {}

/* ************************************************************************* */

public:

    /**
     * @brief returns if input is empty.
     */
    inline bool empty()
    {
        return get() == std::char_traits<ReadMode>::eof();
        //return m_sb->in_avail() <= 0;
    }

    /**
     * @brief read current character.
     */
    inline ReadMode get()
    {
        return static_cast<ReadMode>(m_sb->sgetc());
    }

    /**
     * @brief read current character and move to next.
     */
    inline ReadMode extract()
    {
        return static_cast<ReadMode>(m_sb->sbumpc());
    }

    /**
     * @brief move to next character and read it.
     */
    inline ReadMode getNext()
    {
        return static_cast<ReadMode>(m_sb->snextc());
    }

    /**
     * @brief return to previous character and read it.
     */
    inline ReadMode unget()
    {
        return static_cast<ReadMode>(m_sb->sungetc());
    }

    /* ************************************************************************* */

public:

    /**
     * @brief returns tokenizer iterator pointing to currect token.
     */
    inline SourceIterator begin() noexcept
    {
        return SourceIterator(this);
    }

    /**
     * @brief returns tokenizer iterator pointing to token with end.
     */
    inline SourceIterator end() noexcept
    {
        return SourceIterator(nullptr);
    }
};

/* ************************************************************************* */

inline char SourceIterator::operator*() const
{
    return m_source->get();
}

inline SourceIterator& SourceIterator::operator++()
{
    m_source->extract();
    return *this;
}

inline SourceIterator SourceIterator::operator++(int)
{
    SourceIterator tmp(*this);
    operator++();
    return tmp;
}

/* ************************************************************************* */

}
}
}

/* ************************************************************************* */
<commit_msg>returns integers without conversion to char<commit_after>/* ************************************************************************* */
/* This file is part of Shard.                                               */
/*                                                                           */
/* Shard is free software: you can redistribute it and/or modify             */
/* it under the terms of the GNU Affero General Public License as            */
/* published by the Free Software Foundation.                                */
/*                                                                           */
/* This program is distributed in the hope that it will be useful,           */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the              */
/* GNU Affero General Public License for more details.                       */
/*                                                                           */
/* You should have received a copy of the GNU Affero General Public License  */
/* along with this program. If not, see <http://www.gnu.org/licenses/>.      */
/* ************************************************************************* */

#pragma once

/* ************************************************************************* */

#include <fstream>

// Shard
#include "shard/Path.hpp"
#include "shard/String.hpp"
#include "shard/ViewPtr.hpp"
#include "shard/UniquePtr.hpp"

/* ************************************************************************* */

namespace shard {
inline namespace v1 {
namespace tokenizer {

/* ************************************************************************* */

using ReadMode = char;

/* ************************************************************************* */

class Source; //FWD declaration

/* ************************************************************************* */

class SourceIterator
{

protected:

    ViewPtr<Source> m_source;

public:

    /**
     * @brief constructs empty SourceIterator.
     */
    SourceIterator() = default;

    /**
     * @brief constructs SourceIterator for given Source.
     */
    explicit SourceIterator(ViewPtr<Source> source):
        m_source(source) {}

    inline ReadMode operator*() const;
    inline SourceIterator& operator++();
    inline SourceIterator operator++(int);

    /**
     * @brief returns pointer to related Source.
     */
    inline ViewPtr<Source> getSource() const noexcept
    {
        return m_source;
    }
};

/* ************************************************************************* */

inline bool operator==(const SourceIterator& lhs, const SourceIterator& rhs)
{
    return (lhs.getSource() == nullptr || (*lhs) == std::char_traits<ReadMode>::eof())
        && (rhs.getSource() == nullptr || (*rhs) == std::char_traits<ReadMode>::eof());
}

inline bool operator!=(const SourceIterator& lhs, const SourceIterator& rhs)
{
    return !(lhs == rhs);
}

/* ************************************************************************* */

class Source
{

protected:

    UniquePtr<std::basic_streambuf<ReadMode>> m_sb;

public:

    /**
     * @brief constructs Source with input from file.
     */
    explicit Source (const Path& path):
            m_sb([](const auto& l_path)
            {
                auto ptr = makeUnique<std::basic_filebuf<ReadMode>>();
                ptr->open(l_path, std::ios_base::in | std::ios_base::binary);
                return ptr;
            }(path)) {}

    /**
     * @brief constructs Source with input from string.
     */
    explicit Source (const String& source):
            m_sb(makeUnique<std::basic_stringbuf<ReadMode>>(source)) {}

/* ************************************************************************* */

public:

    /**
     * @brief returns if input is empty.
     */
    inline bool empty()
    {
        return get() == std::char_traits<ReadMode>::eof();
        //return m_sb->in_avail() <= 0;
    }

    /**
     * @brief read current character.
     */
    inline int get()
    {
        return m_sb->sgetc();
    }

    /**
     * @brief read current character and move to next.
     */
    inline int extract()
    {
        return m_sb->sbumpc();
    }

    /**
     * @brief move to next character and read it.
     */
    inline int getNext()
    {
        return m_sb->snextc();
    }

    /**
     * @brief return to previous character and read it.
     */
    inline int unget()
    {
        return m_sb->sungetc();
    }

    /* ************************************************************************* */

public:

    /**
     * @brief returns tokenizer iterator pointing to currect token.
     */
    inline SourceIterator begin() noexcept
    {
        return SourceIterator(this);
    }

    /**
     * @brief returns tokenizer iterator pointing to token with end.
     */
    inline SourceIterator end() noexcept
    {
        return SourceIterator(nullptr);
    }
};

/* ************************************************************************* */

inline int SourceIterator::operator*() const
{
    return m_source->get();
}

inline SourceIterator& SourceIterator::operator++()
{
    m_source->extract();
    return *this;
}

inline SourceIterator SourceIterator::operator++(int)
{
    SourceIterator tmp(*this);
    operator++();
    return tmp;
}

/* ************************************************************************* */

}
}
}

/* ************************************************************************* */
<|endoftext|>


<commit_before>/***************************************************************************
* Copyright (c) 2016, Johan Mabille and Sylvain Corlay                     *
*                                                                          *
* Distributed under the terms of the BSD 3-Clause License.                 *
*                                                                          *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/

#ifndef XTENSOR_CONFIG_HPP
#define XTENSOR_CONFIG_HPP

#define XTENSOR_VERSION_MAJOR 0
#define XTENSOR_VERSION_MINOR 3
#define XTENSOR_VERSION_PATCH 0
#endif
<commit_msg>Release 0.3.1<commit_after>/***************************************************************************
* Copyright (c) 2016, Johan Mabille and Sylvain Corlay                     *
*                                                                          *
* Distributed under the terms of the BSD 3-Clause License.                 *
*                                                                          *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/

#ifndef XTENSOR_CONFIG_HPP
#define XTENSOR_CONFIG_HPP

#define XTENSOR_VERSION_MAJOR 0
#define XTENSOR_VERSION_MINOR 3
#define XTENSOR_VERSION_PATCH 1
#endif
<|endoftext|>


<commit_before>#include "cuda_runtime.h"
#include "device_launch_parameters.h"

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>

#include <imgui.h>

#include "aten.h"
#include "atenscene.h"
#include "idaten.h"

#include "scenedefs.h"

#define ENABLE_ENVMAP

static int WIDTH = 1280;
static int HEIGHT = 720;
static const char* TITLE = "multigpu";

#ifdef ENABLE_OMP
static uint32_t g_threadnum = 8;
#else
static uint32_t g_threadnum = 1;
#endif

static aten::PinholeCamera g_camera;
static bool g_isCameraDirty = false;

static aten::AcceleratedScene<aten::GPUBvh> g_scene;

static idaten::GpuProxy<idaten::PathTracing> g_tracer[2];

static const idaten::TileDomain g_tileDomain[2] = {
	{   0, 0, 640, 720 },
	{ 640, 0, 640, 720 },
};

static aten::visualizer* g_visualizer;

static bool g_willShowGUI = true;
static bool g_willTakeScreenShot = false;
static int g_cntScreenShot = 0;

static int g_maxSamples = 1;
static int g_maxBounce = 5;

void onRun(aten::window* window)
{
	if (g_isCameraDirty) {
		g_camera.update();

		auto camparam = g_camera.param();
		camparam.znear = real(0.1);
		camparam.zfar = real(10000.0);

		for (int i = 0; i < AT_COUNTOF(g_tracer); i++) {
			g_tracer[i].getRenderer().updateCamera(camparam);
		}
		g_isCameraDirty = false;

		g_visualizer->clear();
	}

	aten::timer timer;
	timer.begin();

	g_tracer[0].render(
		g_tileDomain[0],
		g_maxSamples,
		g_maxBounce);

	auto cudaelapsed = timer.end();

	g_visualizer->render(false);

	if (g_willTakeScreenShot) {
		static char buffer[1024];
		::sprintf(buffer, "sc_%d.png\0", g_cntScreenShot);

		g_visualizer->takeScreenshot(buffer);

		g_willTakeScreenShot = false;
		g_cntScreenShot++;

		AT_PRINTF("Take Screenshot[%s]\n", buffer);
	}

	if (g_willShowGUI)
	{
		ImGui::Text("%.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
		ImGui::Text("cuda : %.3f ms", cudaelapsed);
		ImGui::Text("%.3f Mrays/sec", (WIDTH * HEIGHT * g_maxSamples) / real(1000 * 1000) * (real(1000) / cudaelapsed));

		window->drawImGui();
	}
}

void onClose()
{

}

bool g_isMouseLBtnDown = false;
bool g_isMouseRBtnDown = false;
int g_prevX = 0;
int g_prevY = 0;

void onMouseBtn(bool left, bool press, int x, int y)
{
	g_isMouseLBtnDown = false;
	g_isMouseRBtnDown = false;

	if (press) {
		g_prevX = x;
		g_prevY = y;

		g_isMouseLBtnDown = left;
		g_isMouseRBtnDown = !left;
	}
}

void onMouseMove(int x, int y)
{
	if (g_isMouseLBtnDown) {
		aten::CameraOperator::rotate(
			g_camera,
			WIDTH, HEIGHT,
			g_prevX, g_prevY,
			x, y);
		g_isCameraDirty = true;
	}
	else if (g_isMouseRBtnDown) {
		aten::CameraOperator::move(
			g_camera,
			g_prevX, g_prevY,
			x, y,
			real(0.001));
		g_isCameraDirty = true;
	}

	g_prevX = x;
	g_prevY = y;
}

void onMouseWheel(int delta)
{
	aten::CameraOperator::dolly(g_camera, delta * real(0.1));
	g_isCameraDirty = true;
}

void onKey(bool press, aten::Key key)
{
	static const real offset = real(0.1);

	if (press) {
		if (key == aten::Key::Key_F1) {
			g_willShowGUI = !g_willShowGUI;
			return;
		}
		else if (key == aten::Key::Key_F2) {
			g_willTakeScreenShot = true;
			return;
		}
	}

	if (press) {
		switch (key) {
		case aten::Key::Key_W:
		case aten::Key::Key_UP:
			aten::CameraOperator::moveForward(g_camera, offset);
			break;
		case aten::Key::Key_S:
		case aten::Key::Key_DOWN:
			aten::CameraOperator::moveForward(g_camera, -offset);
			break;
		case aten::Key::Key_D:
		case aten::Key::Key_RIGHT:
			aten::CameraOperator::moveRight(g_camera, offset);
			break;
		case aten::Key::Key_A:
		case aten::Key::Key_LEFT:
			aten::CameraOperator::moveRight(g_camera, -offset);
			break;
		case aten::Key::Key_Z:
			aten::CameraOperator::moveUp(g_camera, offset);
			break;
		case aten::Key::Key_X:
			aten::CameraOperator::moveUp(g_camera, -offset);
			break;
		case aten::Key::Key_R:
		{
			aten::vec3 pos, at;
			real vfov;
			Scene::getCameraPosAndAt(pos, at, vfov);

			g_camera.init(
				pos,
				at,
				aten::vec3(0, 1, 0),
				vfov,
#ifdef ENABLE_GEOMRENDERING
				WIDTH >> 1, HEIGHT >> 1);
#else
				WIDTH, HEIGHT);
#endif
		}
			break;
		default:
			break;
		}

		g_isCameraDirty = true;
	}
}

int main()
{
	idaten::initCuda();

	aten::timer::init();
	aten::OMPUtil::setThreadNum(g_threadnum);

	aten::initSampler(WIDTH, HEIGHT);

	aten::window::init(
		WIDTH, HEIGHT, TITLE,
		onRun,
		onClose,
		onMouseBtn,
		onMouseMove,
		onMouseWheel,
		onKey);

	g_visualizer = aten::visualizer::init(WIDTH, HEIGHT);

	aten::GammaCorrection gamma;
	gamma.init(
		WIDTH, HEIGHT,
		"../shader/fullscreen_vs.glsl",
		"../shader/gamma_fs.glsl");

	g_visualizer->addPostProc(&gamma);
	//aten::visualizer::addPostProc(&blitter);

	aten::vec3 pos, at;
	real vfov;
	Scene::getCameraPosAndAt(pos, at, vfov);

	g_camera.init(
		pos,
		at,
		aten::vec3(0, 1, 0),
		vfov,
		WIDTH, HEIGHT);

	Scene::makeScene(&g_scene);
	g_scene.build();

	auto envmap = aten::ImageLoader::load("../../asset/envmap/studio015.hdr");
	aten::envmap bg;
	bg.init(envmap);
	aten::ImageBasedLight ibl(&bg);

	g_scene.addImageBasedLight(&ibl);

	std::vector<aten::GeomParameter> shapeparams;
	std::vector<aten::PrimitiveParamter> primparams;
	std::vector<aten::LightParameter> lightparams;
	std::vector<aten::MaterialParameter> mtrlparms;
	std::vector<aten::vertex> vtxparams;

	aten::DataCollector::collect(
		shapeparams,
		primparams,
		lightparams,
		mtrlparms,
		vtxparams);

	const auto& nodes = g_scene.getAccel()->getNodes();
	const auto& mtxs = g_scene.getAccel()->getMatrices();
	//aten::bvh::dumpCollectedNodes(nodes, "nodes.txt");

	std::vector<idaten::TextureResource> tex;
	{
		auto texs = aten::texture::getTextures();

		for (const auto t : texs) {
			tex.push_back(
				idaten::TextureResource(t->colors(), t->width(), t->height()));
		}
	}

	for (auto& l : lightparams) {
		if (l.type == aten::LightType::IBL) {
			l.envmap.idx = envmap->id();
		}
	}

	auto camparam = g_camera.param();
	camparam.znear = real(0.1);
	camparam.zfar = real(10000.0);

	g_tracer[0].init(0);
	g_tracer[1].init(1);

	for (int i = 0; i < AT_COUNTOF(g_tracer); i++)
	{
		const auto& tileDomain = g_tileDomain[i];

		g_tracer[i].setCurrent();

		g_tracer[i].getRenderer().getCompaction().init(
			tileDomain.w * tileDomain.h,
			1024);

		g_tracer[i].getRenderer().update(
			aten::visualizer::getTexHandle(),
			WIDTH, HEIGHT,
			camparam,
			shapeparams,
			mtrlparms,
			lightparams,
			nodes,
			primparams,
			vtxparams,
			mtxs,
			tex, idaten::EnvmapResource(envmap->id(), ibl.getAvgIlluminace(), real(4)));
	}

	aten::window::run();

	aten::window::terminate();
}
<commit_msg>Fix bug that value to allocate device memory is wrong.<commit_after>#include "cuda_runtime.h"
#include "device_launch_parameters.h"

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>

#include <imgui.h>

#include "aten.h"
#include "atenscene.h"
#include "idaten.h"

#include "scenedefs.h"

#define ENABLE_ENVMAP

static int WIDTH = 1280;
static int HEIGHT = 720;
static const char* TITLE = "multigpu";

#ifdef ENABLE_OMP
static uint32_t g_threadnum = 8;
#else
static uint32_t g_threadnum = 1;
#endif

static aten::PinholeCamera g_camera;
static bool g_isCameraDirty = false;

static aten::AcceleratedScene<aten::GPUBvh> g_scene;

static idaten::GpuProxy<idaten::PathTracing> g_tracer[2];

static const idaten::TileDomain g_tileDomain[2] = {
	{   0, 0, 640, 720 },
	{ 640, 0, 640, 720 },
};

static aten::visualizer* g_visualizer = nullptr;

static bool g_willShowGUI = true;
static bool g_willTakeScreenShot = false;
static int g_cntScreenShot = 0;

static int g_maxSamples = 1;
static int g_maxBounce = 5;

void onRun(aten::window* window)
{
	if (g_isCameraDirty) {
		g_camera.update();

		auto camparam = g_camera.param();
		camparam.znear = real(0.1);
		camparam.zfar = real(10000.0);

		for (int i = 0; i < AT_COUNTOF(g_tracer); i++) {
			g_tracer[i].getRenderer().updateCamera(camparam);
		}
		g_isCameraDirty = false;

		g_visualizer->clear();
	}

	aten::timer timer;
	timer.begin();

	g_tracer[0].render(
		g_tileDomain[0],
		g_maxSamples,
		g_maxBounce);

	auto cudaelapsed = timer.end();

	g_visualizer->render(false);

	if (g_willTakeScreenShot) {
		static char buffer[1024];
		::sprintf(buffer, "sc_%d.png\0", g_cntScreenShot);

		g_visualizer->takeScreenshot(buffer);

		g_willTakeScreenShot = false;
		g_cntScreenShot++;

		AT_PRINTF("Take Screenshot[%s]\n", buffer);
	}

	if (g_willShowGUI)
	{
		ImGui::Text("%.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
		ImGui::Text("cuda : %.3f ms", cudaelapsed);
		ImGui::Text("%.3f Mrays/sec", (WIDTH * HEIGHT * g_maxSamples) / real(1000 * 1000) * (real(1000) / cudaelapsed));

		window->drawImGui();
	}
}

void onClose()
{

}

bool g_isMouseLBtnDown = false;
bool g_isMouseRBtnDown = false;
int g_prevX = 0;
int g_prevY = 0;

void onMouseBtn(bool left, bool press, int x, int y)
{
	g_isMouseLBtnDown = false;
	g_isMouseRBtnDown = false;

	if (press) {
		g_prevX = x;
		g_prevY = y;

		g_isMouseLBtnDown = left;
		g_isMouseRBtnDown = !left;
	}
}

void onMouseMove(int x, int y)
{
	if (g_isMouseLBtnDown) {
		aten::CameraOperator::rotate(
			g_camera,
			WIDTH, HEIGHT,
			g_prevX, g_prevY,
			x, y);
		g_isCameraDirty = true;
	}
	else if (g_isMouseRBtnDown) {
		aten::CameraOperator::move(
			g_camera,
			g_prevX, g_prevY,
			x, y,
			real(0.001));
		g_isCameraDirty = true;
	}

	g_prevX = x;
	g_prevY = y;
}

void onMouseWheel(int delta)
{
	aten::CameraOperator::dolly(g_camera, delta * real(0.1));
	g_isCameraDirty = true;
}

void onKey(bool press, aten::Key key)
{
	static const real offset = real(0.1);

	if (press) {
		if (key == aten::Key::Key_F1) {
			g_willShowGUI = !g_willShowGUI;
			return;
		}
		else if (key == aten::Key::Key_F2) {
			g_willTakeScreenShot = true;
			return;
		}
	}

	if (press) {
		switch (key) {
		case aten::Key::Key_W:
		case aten::Key::Key_UP:
			aten::CameraOperator::moveForward(g_camera, offset);
			break;
		case aten::Key::Key_S:
		case aten::Key::Key_DOWN:
			aten::CameraOperator::moveForward(g_camera, -offset);
			break;
		case aten::Key::Key_D:
		case aten::Key::Key_RIGHT:
			aten::CameraOperator::moveRight(g_camera, offset);
			break;
		case aten::Key::Key_A:
		case aten::Key::Key_LEFT:
			aten::CameraOperator::moveRight(g_camera, -offset);
			break;
		case aten::Key::Key_Z:
			aten::CameraOperator::moveUp(g_camera, offset);
			break;
		case aten::Key::Key_X:
			aten::CameraOperator::moveUp(g_camera, -offset);
			break;
		case aten::Key::Key_R:
		{
			aten::vec3 pos, at;
			real vfov;
			Scene::getCameraPosAndAt(pos, at, vfov);

			g_camera.init(
				pos,
				at,
				aten::vec3(0, 1, 0),
				vfov,
				WIDTH, HEIGHT);
		}
			break;
		default:
			break;
		}

		g_isCameraDirty = true;
	}
}

int main()
{
	idaten::initCuda();

	aten::timer::init();
	aten::OMPUtil::setThreadNum(g_threadnum);

	aten::initSampler(WIDTH, HEIGHT);

	aten::window::init(
		WIDTH, HEIGHT, TITLE,
		onRun,
		onClose,
		onMouseBtn,
		onMouseMove,
		onMouseWheel,
		onKey);

	g_visualizer = aten::visualizer::init(WIDTH, HEIGHT);

	aten::GammaCorrection gamma;
	gamma.init(
		WIDTH, HEIGHT,
		"../shader/fullscreen_vs.glsl",
		"../shader/gamma_fs.glsl");

	g_visualizer->addPostProc(&gamma);
	//aten::visualizer::addPostProc(&blitter);

	aten::vec3 pos, at;
	real vfov;
	Scene::getCameraPosAndAt(pos, at, vfov);

	g_camera.init(
		pos,
		at,
		aten::vec3(0, 1, 0),
		vfov,
		WIDTH, HEIGHT);

	Scene::makeScene(&g_scene);
	g_scene.build();

	auto envmap = aten::ImageLoader::load("../../asset/envmap/studio015.hdr");
	aten::envmap bg;
	bg.init(envmap);
	aten::ImageBasedLight ibl(&bg);

	g_scene.addImageBasedLight(&ibl);

	std::vector<aten::GeomParameter> shapeparams;
	std::vector<aten::PrimitiveParamter> primparams;
	std::vector<aten::LightParameter> lightparams;
	std::vector<aten::MaterialParameter> mtrlparms;
	std::vector<aten::vertex> vtxparams;

	aten::DataCollector::collect(
		shapeparams,
		primparams,
		lightparams,
		mtrlparms,
		vtxparams);

	const auto& nodes = g_scene.getAccel()->getNodes();
	const auto& mtxs = g_scene.getAccel()->getMatrices();
	//aten::bvh::dumpCollectedNodes(nodes, "nodes.txt");

	std::vector<idaten::TextureResource> tex;
	{
		auto texs = aten::texture::getTextures();

		for (const auto t : texs) {
			tex.push_back(
				idaten::TextureResource(t->colors(), t->width(), t->height()));
		}
	}

	for (auto& l : lightparams) {
		if (l.type == aten::LightType::IBL) {
			l.envmap.idx = envmap->id();
		}
	}

	auto camparam = g_camera.param();
	camparam.znear = real(0.1);
	camparam.zfar = real(10000.0);

	g_tracer[0].init(0);
	g_tracer[1].init(1);

	for (int i = 0; i < AT_COUNTOF(g_tracer); i++)
	{
		const auto& tileDomain = g_tileDomain[i];

		g_tracer[i].setCurrent();

		g_tracer[i].getRenderer().getCompaction().init(
			tileDomain.w * tileDomain.h,
			1024);

		g_tracer[i].getRenderer().update(
			aten::visualizer::getTexHandle(),
			tileDomain.w, tileDomain.h,
			camparam,
			shapeparams,
			mtrlparms,
			lightparams,
			nodes,
			primparams,
			vtxparams,
			mtxs,
			tex, idaten::EnvmapResource(envmap->id(), ibl.getAvgIlluminace(), real(4)));
	}

	aten::window::run();

	aten::window::terminate();
}
<|endoftext|>


<commit_before>/**
 * @file transformer.cpp
 *
 * @date May, 2014
 * @author Tack
 */

#include "transformer.h"
#include "plugin_factory.h"
#include "logger_factory.h"
#include <boost/lexical_cast.hpp>
#include "json_parser.h"
#include "util.h"
#include "NFmiGrid.h"

#define HIMAN_AUXILIARY_INCLUDE

#include "fetcher.h"

#undef HIMAN_AUXILIARY_INCLUDE

using namespace std;
using namespace himan::plugin;

#include "cuda_helper.h"

transformer::transformer() : itsBase(0.0), itsScale(1.0), itsTargetUnivID(999)
{
	itsClearTextFormula = "target_param = source_param * itsScale + itsBase";
	itsCudaEnabledCalculation = false;

	itsLogger = unique_ptr<logger> (logger_factory::Instance()->GetLog("transformer"));
}

vector<himan::level> transformer::LevelsFromString(const string& levelType, const string& levelValues) const
{
	string levelTypeUpper = levelType;
	boost::to_upper(levelTypeUpper);

	HPLevelType theLevelType;

	if (levelTypeUpper == "HEIGHT")
	{
		theLevelType = kHeight;
	}
	else if (levelTypeUpper == "PRESSURE")
	{
		theLevelType = kPressure;
	}
	else if (levelTypeUpper == "HYBRID")
	{
		theLevelType = kHybrid;
	}
	else if (levelTypeUpper == "GROUND")
	{
		theLevelType = kGround;
	}
	else if (levelTypeUpper == "MEANSEA")
	{
		theLevelType = kMeanSea;
	}
	else
	{
		throw runtime_error("Unknown level type: " + levelType);
	}

	// can cause exception, what will happen then ?

	vector<string> levelsStr = util::Split(levelValues, ",", true);

	vector<level> levels;

	for (size_t i = 0; i < levelsStr.size(); i++)
	{
		levels.push_back(level(theLevelType, boost::lexical_cast<float> (levelsStr[i]), levelType));
	}

	return levels;
}

void transformer::SetAdditionalParameters()
{
	std::string itsSourceLevelType;
	std::string SourceLevels;

	if(itsConfiguration->Options().count("base"))
	{
		itsBase = boost::lexical_cast<double>(itsConfiguration->GetValue("base"));
	}
	else
	{
		itsLogger->Warning("Base not specified, using default value 0.0");
	}

	if(itsConfiguration->Options().count("scale"))
	{
		itsScale = boost::lexical_cast<double>(itsConfiguration->GetValue("scale"));
	}
	else
	{
		itsLogger->Warning("Scale not specified, using default value 1.0");
	}

	if(itsConfiguration->Options().count("target_univ_ID"))
	{
		itsTargetUnivID = boost::lexical_cast<int>(itsConfiguration->GetValue("target_univ_ID"));
	}
	else
	{
		itsLogger->Warning("Target_univ_ID not specified, using  default value 999");
	}

	if(itsConfiguration->Options().count("target_param"))
	{
		itsTargetParam = itsConfiguration->GetValue("target_param");
	}
	else
	{
		itsLogger->Warning("Target_param not specified. Exiting program.");
		exit(1);
	}

	if(itsConfiguration->Options().count("source_param"))
	{
		itsSourceParam = itsConfiguration->GetValue("source_param");
	}
	else
	{
		itsSourceParam = itsTargetParam;
		itsLogger->Warning("Source_param not specified, source_param set to target_param");
	}

	if(itsConfiguration->Options().count("source_level_type"))
	{
		itsSourceLevelType = itsConfiguration->GetValue("source_level_type");
	}
	else
	{
		itsSourceLevelType = itsConfiguration->GetValue("leveltype");
		itsLogger->Warning("Source_level_type not specified, value set to leveltype");
	}

	if(itsConfiguration->Options().count("source_levels"))
	{
		SourceLevels = itsConfiguration->GetValue("source_levels");
	}
	else
	{
		SourceLevels = itsConfiguration->GetValue("levels");
		itsLogger->Warning("Source_levels not specified, values set to target levels");
	}

	// looks useful to use this function to create source_levels
	itsSourceLevels = LevelsFromString(itsSourceLevelType, SourceLevels);
}

void transformer::Process(std::shared_ptr<const plugin_configuration> conf)
{
	Init(conf);
	SetAdditionalParameters();

	/*
	 * Set target parameter to T
	 * - name T-C
	 * - univ_id 4
	 * - grib2 descriptor 0'00'000
	 *
	 * We need to specify grib and querydata parameter information
	 * since we don't know which one will be the output format.
	 *
	 */

	vector<param> theParams;

	param requestedParam(itsTargetParam, itsTargetUnivID);

	// GRIB 2

	//requestedParam.GribDiscipline(pt.get<string>("target_GribDiscipline"));
	//requestedParam.GribCategory(pt.get<string>("target_GribCategory"));
	//requestedParam.GribParameter(pt.get<string>("target_GribParameter"));

	// GRIB 1

	theParams.push_back(requestedParam);

	SetParams(theParams);

	Start();

}

/*
 * Calculate()
 *
 * This function does the actual calculation.
 */

void transformer::Calculate(shared_ptr<info> myTargetInfo, unsigned short threadIndex)
{
	shared_ptr<fetcher> aFetcher = dynamic_pointer_cast <fetcher> (plugin_factory::Instance()->Plugin("fetcher"));

	// Required source parameter

	param InputParam(itsSourceParam);

	unique_ptr<logger> myThreadedLogger = std::unique_ptr<logger> (logger_factory::Instance()->GetLog("transformerThread #" + boost::lexical_cast<string> (threadIndex)));

	ResetNonLeadingDimension(myTargetInfo);

	myTargetInfo->FirstParam();

	while (AdjustNonLeadingDimension(myTargetInfo))
	{

		myThreadedLogger->Debug("Calculating time " + myTargetInfo->Time().ValidDateTime()->String("%Y%m%d%H%M") +
								" level " + boost::lexical_cast<string> (myTargetInfo->Level().Value()));

		// Source info for T

		shared_ptr<info> sourceInfo;

		try
		{
			sourceInfo = aFetcher->Fetch(itsConfiguration,
								 myTargetInfo->Time(),
								 itsSourceLevels[myTargetInfo->LevelIndex()],
								 InputParam);
		}
		catch (HPExceptionType& e)
		{
			switch (e)
			{
				case kFileDataNotFound:
					itsLogger->Warning("Skipping step " + boost::lexical_cast<string> (myTargetInfo->Time().Step()) + ", level " + boost::lexical_cast<string> (myTargetInfo->Level().Value()));
					myTargetInfo->Data()->Fill(kFloatMissing);

					if (itsConfiguration->StatisticsEnabled())
					{
						itsConfiguration->Statistics()->AddToMissingCount(myTargetInfo->Grid()->Size());
						itsConfiguration->Statistics()->AddToValueCount(myTargetInfo->Grid()->Size());
					}

					continue;
					break;

				default:
					throw runtime_error(ClassName() + ": Unable to proceed");
					break;
			}
		}

		SetAB(myTargetInfo, sourceInfo);

		size_t missingCount = 0;
		size_t count = 0;

		shared_ptr<NFmiGrid> targetGrid(myTargetInfo->Grid()->ToNewbaseGrid());

		bool equalGrids = (*myTargetInfo->Grid() == *sourceInfo->Grid());

		string deviceType;

/*
#ifdef HAVE_CUDA

		// If we read packed data but grids are not equal we cannot use cuda
		// for calculations (our cuda routines do not know how to interpolate)

		if (!equalGrids && sourceInfo->Grid()->IsPackedData())
		{
			myThreadedLogger->Debug("Unpacking for CPU calculation");

			Unpack({sourceInfo});
		}

		if (useCudaInThisThread && equalGrids)
		{

			deviceType = "GPU";

			auto opts = CudaPrepare(myTargetInfo, sourceInfo);

			transformer_cuda::Process(*opts);

			missingCount = opts->missing;
			count = opts->N;

			CudaFinish(move(opts), myTargetInfo, sourceInfo);

		}
		else
#endif
*/
		{

			deviceType = "CPU";

			shared_ptr<NFmiGrid> sourceGrid(sourceInfo->Grid()->ToNewbaseGrid());

			assert(targetGrid->Size() == myTargetInfo->Data()->Size());

			myTargetInfo->ResetLocation();

			targetGrid->Reset();

			while (myTargetInfo->NextLocation() && targetGrid->Next())
			{

				count++;

				double value = kFloatMissing;

				InterpolateToPoint(targetGrid, sourceGrid, equalGrids, value);

				if (value == kFloatMissing)
				{
					missingCount++;

					myTargetInfo->Value(kFloatMissing);
					continue;
				}

				double newValue = value * itsScale + itsBase;

				if (!myTargetInfo->Value(newValue))
				{
					throw runtime_error(ClassName() + ": Failed to set value to matrix");
				}
			}

			/*
			 * Newbase normalizes scanning mode to bottom left -- if that's not what
			 * the target scanning mode is, we have to swap the data back.
			 */

			SwapTo(myTargetInfo, kBottomLeft);

		}

		if (itsConfiguration->StatisticsEnabled())
		{
			itsConfiguration->Statistics()->AddToMissingCount(missingCount);
			itsConfiguration->Statistics()->AddToValueCount(count);
		}

		/*
		 * Now we are done for this level
		 *
		 * Clone info-instance to writer since it might change our descriptor places
		 */

		myThreadedLogger->Info("[" + deviceType + "] Missing values: " + boost::lexical_cast<string> (missingCount) + "/" + boost::lexical_cast<string> (count));

		if (itsConfiguration->FileWriteOption() != kSingleFile)
		{
			WriteToFile(myTargetInfo);
		}

	}
}

/*
#ifdef HAVE_CUDA

unique_ptr<transformer_cuda::options> transformer::CudaPrepare( shared_ptr<info> myTargetInfo, shared_ptr<info> sourceInfo)
{
	unique_ptr<transformer_cuda::options> opts(new transformer_cuda::options);

	opts->N = sourceInfo->Data()->Size();

	opts->base = itsBase;
	opts->scale = itsScale;

	opts->source = sourceInfo->ToSimple();
	opts->dest = myTargetInfo->ToSimple();

	return opts;
}

void transformer::CudaFinish(unique_ptr<transformer_cuda::options> opts, shared_ptr<info> myTargetInfo, shared_ptr<info> sourceInfo)
{
	// Copy data back to infos

	CopyDataFromSimpleInfo(myTargetInfo, opts->dest, false);

	if (sourceInfo->Grid()->IsPackedData())
	{
		CopyDataFromSimpleInfo(sourceInfo, opts->source, true);
	}

	SwapTo(myTargetInfo, sourceInfo->Grid()->ScanningMode());

}

#endif
*/
<commit_msg>Throw error and exit when source level or target parameter unspecified. If scale = 1 and base = 0 skip scaling calculation.<commit_after>/**
 * @file transformer.cpp
 *
 * @date May, 2014
 * @author Tack
 */

#include "transformer.h"
#include "plugin_factory.h"
#include "logger_factory.h"
#include <boost/lexical_cast.hpp>
#include "json_parser.h"
#include "util.h"
#include "NFmiGrid.h"

#define HIMAN_AUXILIARY_INCLUDE

#include "fetcher.h"

#undef HIMAN_AUXILIARY_INCLUDE

using namespace std;
using namespace himan::plugin;

#include "cuda_helper.h"

transformer::transformer() : itsBase(0.0), itsScale(1.0), itsTargetUnivID(999)
{
	itsClearTextFormula = "target_param = source_param * itsScale + itsBase";
	itsCudaEnabledCalculation = false;

	itsLogger = unique_ptr<logger> (logger_factory::Instance()->GetLog("transformer"));
}

vector<himan::level> transformer::LevelsFromString(const string& levelType, const string& levelValues) const
{
	string levelTypeUpper = levelType;
	boost::to_upper(levelTypeUpper);

	HPLevelType theLevelType;

	if (levelTypeUpper == "HEIGHT")
	{
		theLevelType = kHeight;
	}
	else if (levelTypeUpper == "PRESSURE")
	{
		theLevelType = kPressure;
	}
	else if (levelTypeUpper == "HYBRID")
	{
		theLevelType = kHybrid;
	}
	else if (levelTypeUpper == "GROUND")
	{
		theLevelType = kGround;
	}
	else if (levelTypeUpper == "MEANSEA")
	{
		theLevelType = kMeanSea;
	}
	else
	{
		throw runtime_error("Unknown level type: " + levelType);
	}

	// can cause exception, what will happen then ?

	vector<string> levelsStr = util::Split(levelValues, ",", true);

	vector<level> levels;

	for (size_t i = 0; i < levelsStr.size(); i++)
	{
		levels.push_back(level(theLevelType, boost::lexical_cast<float> (levelsStr[i]), levelType));
	}

	return levels;
}

void transformer::SetAdditionalParameters()
{
	std::string itsSourceLevelType;
	std::string SourceLevels;

	if(itsConfiguration->Options().count("base"))
	{
		itsBase = boost::lexical_cast<double>(itsConfiguration->GetValue("base"));
	}
	else
	{
		itsLogger->Warning("Base not specified, using default value 0.0");
	}

	if(itsConfiguration->Options().count("scale"))
	{
		itsScale = boost::lexical_cast<double>(itsConfiguration->GetValue("scale"));
	}
	else
	{
		itsLogger->Warning("Scale not specified, using default value 1.0");
	}

	if(itsConfiguration->Options().count("target_univ_ID"))
	{
		itsTargetUnivID = boost::lexical_cast<int>(itsConfiguration->GetValue("target_univ_ID"));
	}
	else
	{
		itsLogger->Warning("Target_univ_ID not specified, using  default value 999");
	}

	if(itsConfiguration->Options().count("target_param"))
	{
		itsTargetParam = itsConfiguration->GetValue("target_param");
	}
	else
	{
		throw runtime_error("Transformer_plugin: target_param not specified.");
		exit(1);
	}

	if(itsConfiguration->Options().count("source_param"))
	{
		itsSourceParam = itsConfiguration->GetValue("source_param");
	}
	else
	{
		itsSourceParam = itsTargetParam;
		itsLogger->Warning("Source_param not specified, source_param set to target_param");
	}

	if(itsConfiguration->Options().count("source_level_type"))
	{
		itsSourceLevelType = itsConfiguration->GetValue("source_level_type");
	}
	else
	{
		throw runtime_error("Transformer_plugin: source_level_type not specified.");
		exit(1);
	}

	if(itsConfiguration->Options().count("source_levels"))
	{
		SourceLevels = itsConfiguration->GetValue("source_levels");
	}
	else
	{
		throw runtime_error("Transformer_plugin: source_level_type not specified.");
		exit(1);
	}

	// looks useful to use this function to create source_levels
	itsSourceLevels = LevelsFromString(itsSourceLevelType, SourceLevels);
}

void transformer::Process(std::shared_ptr<const plugin_configuration> conf)
{
	Init(conf);
	SetAdditionalParameters();

	/*
	 * Set target parameter to T
	 * - name T-C
	 * - univ_id 4
	 * - grib2 descriptor 0'00'000
	 *
	 * We need to specify grib and querydata parameter information
	 * since we don't know which one will be the output format.
	 *
	 */

	vector<param> theParams;

	param requestedParam(itsTargetParam, itsTargetUnivID);

	// GRIB 2

	//requestedParam.GribDiscipline(pt.get<string>("target_GribDiscipline"));
	//requestedParam.GribCategory(pt.get<string>("target_GribCategory"));
	//requestedParam.GribParameter(pt.get<string>("target_GribParameter"));

	// GRIB 1

	theParams.push_back(requestedParam);

	SetParams(theParams);

	Start();

}

/*
 * Calculate()
 *
 * This function does the actual calculation.
 */

void transformer::Calculate(shared_ptr<info> myTargetInfo, unsigned short threadIndex)
{
	shared_ptr<fetcher> aFetcher = dynamic_pointer_cast <fetcher> (plugin_factory::Instance()->Plugin("fetcher"));

	// Required source parameter

	param InputParam(itsSourceParam);

	unique_ptr<logger> myThreadedLogger = std::unique_ptr<logger> (logger_factory::Instance()->GetLog("transformerThread #" + boost::lexical_cast<string> (threadIndex)));

	ResetNonLeadingDimension(myTargetInfo);

	myTargetInfo->FirstParam();

	while (AdjustNonLeadingDimension(myTargetInfo))
	{

		myThreadedLogger->Debug("Calculating time " + myTargetInfo->Time().ValidDateTime()->String("%Y%m%d%H%M") +
								" level " + boost::lexical_cast<string> (myTargetInfo->Level().Value()));

		// Source info for T

		shared_ptr<info> sourceInfo;

		try
		{
			sourceInfo = aFetcher->Fetch(itsConfiguration,
								 myTargetInfo->Time(),
								 itsSourceLevels[myTargetInfo->LevelIndex()],
								 InputParam);
		}
		catch (HPExceptionType& e)
		{
			switch (e)
			{
				case kFileDataNotFound:
					itsLogger->Warning("Skipping step " + boost::lexical_cast<string> (myTargetInfo->Time().Step()) + ", level " + boost::lexical_cast<string> (myTargetInfo->Level().Value()));
					myTargetInfo->Data()->Fill(kFloatMissing);

					if (itsConfiguration->StatisticsEnabled())
					{
						itsConfiguration->Statistics()->AddToMissingCount(myTargetInfo->Grid()->Size());
						itsConfiguration->Statistics()->AddToValueCount(myTargetInfo->Grid()->Size());
					}

					continue;
					break;

				default:
					throw runtime_error(ClassName() + ": Unable to proceed");
					break;
			}
		}

		SetAB(myTargetInfo, sourceInfo);

		size_t missingCount = 0;
		size_t count = 0;

		shared_ptr<NFmiGrid> targetGrid(myTargetInfo->Grid()->ToNewbaseGrid());

		bool equalGrids = (*myTargetInfo->Grid() == *sourceInfo->Grid());
		bool levelOnly = (itsScale == 1.0 && itsBase == 0.0);

		string deviceType;

/*
#ifdef HAVE_CUDA

		// If we read packed data but grids are not equal we cannot use cuda
		// for calculations (our cuda routines do not know how to interpolate)

		if (!equalGrids && sourceInfo->Grid()->IsPackedData())
		{
			myThreadedLogger->Debug("Unpacking for CPU calculation");

			Unpack({sourceInfo});
		}

		if (useCudaInThisThread && equalGrids)
		{

			deviceType = "GPU";

			auto opts = CudaPrepare(myTargetInfo, sourceInfo);

			transformer_cuda::Process(*opts);

			missingCount = opts->missing;
			count = opts->N;

			CudaFinish(move(opts), myTargetInfo, sourceInfo);

		}
		else
#endif
*/
		{

			deviceType = "CPU";

			shared_ptr<NFmiGrid> sourceGrid(sourceInfo->Grid()->ToNewbaseGrid());

			assert(targetGrid->Size() == myTargetInfo->Data()->Size());

			myTargetInfo->ResetLocation();

			targetGrid->Reset();

			while (myTargetInfo->NextLocation() && targetGrid->Next())
			{

				count++;

				double value = kFloatMissing;

				InterpolateToPoint(targetGrid, sourceGrid, equalGrids, value);

				if (value == kFloatMissing)
				{
					missingCount++;

					myTargetInfo->Value(kFloatMissing);
					continue;
				}

				if (!levelOnly)
				{
					double newValue = value * itsScale + itsBase;

					if (!myTargetInfo->Value(newValue))
					{
						throw runtime_error(ClassName() + ": Failed to set value to matrix");
					}
				}
				else
				{
					if (!myTargetInfo->Value(value))
					{
						throw runtime_error(ClassName() + ": Failed to set value to matrix");
					}
				}
			}

			/*
			 * Newbase normalizes scanning mode to bottom left -- if that's not what
			 * the target scanning mode is, we have to swap the data back.
			 */

			SwapTo(myTargetInfo, kBottomLeft);

		}

		if (itsConfiguration->StatisticsEnabled())
		{
			itsConfiguration->Statistics()->AddToMissingCount(missingCount);
			itsConfiguration->Statistics()->AddToValueCount(count);
		}

		/*
		 * Now we are done for this level
		 *
		 * Clone info-instance to writer since it might change our descriptor places
		 */

		myThreadedLogger->Info("[" + deviceType + "] Missing values: " + boost::lexical_cast<string> (missingCount) + "/" + boost::lexical_cast<string> (count));

		if (itsConfiguration->FileWriteOption() != kSingleFile)
		{
			WriteToFile(myTargetInfo);
		}

	}
}

/*
#ifdef HAVE_CUDA

unique_ptr<transformer_cuda::options> transformer::CudaPrepare( shared_ptr<info> myTargetInfo, shared_ptr<info> sourceInfo)
{
	unique_ptr<transformer_cuda::options> opts(new transformer_cuda::options);

	opts->N = sourceInfo->Data()->Size();

	opts->base = itsBase;
	opts->scale = itsScale;

	opts->source = sourceInfo->ToSimple();
	opts->dest = myTargetInfo->ToSimple();

	return opts;
}

void transformer::CudaFinish(unique_ptr<transformer_cuda::options> opts, shared_ptr<info> myTargetInfo, shared_ptr<info> sourceInfo)
{
	// Copy data back to infos

	CopyDataFromSimpleInfo(myTargetInfo, opts->dest, false);

	if (sourceInfo->Grid()->IsPackedData())
	{
		CopyDataFromSimpleInfo(sourceInfo, opts->source, true);
	}

	SwapTo(myTargetInfo, sourceInfo->Grid()->ScanningMode());

}

#endif
*/
<|endoftext|>


<commit_before>#include <common/endian.h>

#include <event/event_callback.h>
#include <event/event_main.h>
#include <event/event_system.h>

#include <http/http_protocol.h>

#include <io/net/tcp_server.h>

#include <io/pipe/pipe.h>
#include <io/pipe/pipe_producer.h>
#include <io/pipe/splice.h>

#include <io/socket/simple_server.h>

#include <ssh/ssh_protocol.h>

namespace {
	static uint8_t zero_padding[255];
}

class SSHTransportPipe : public PipeProducer {
	enum State {
		GetIdentificationString,
		GetPacket
	};

	State state_;
	Buffer input_buffer_;

	/* XXX These parameters are different for receive and send.  */
	size_t block_size_;
	size_t mac_length_;

	EventCallback *receive_callback_;
	Action *receive_action_;
public:
	SSHTransportPipe(void)
	: PipeProducer("/ssh/transport/pipe"),
	  state_(GetIdentificationString),
	  block_size_(8),
	  mac_length_(0),
	  receive_callback_(NULL),
	  receive_action_(NULL)
	{
		Buffer identification_string("SSH-2.0-WANProxy " + (std::string)log_ + "\r\n");
		produce(&identification_string);
	}

	~SSHTransportPipe()
	{
		ASSERT(receive_callback_ == NULL);
		ASSERT(receive_action_ == NULL);
	}

	Action *receive(EventCallback *cb)
	{
		ASSERT(receive_callback_ == NULL);
		ASSERT(receive_action_ == NULL);

		/*
		 * XXX
		 * This pattern is implemented about three different
		 * ways in the WANProxy codebase, and they are all kind
		 * of awful.  Need a better way to handle code that
		 * needs executed either on the request of the caller
		 * or when data comes in that satisfies a deferred
		 * callback to a caller.
		 */
		receive_callback_ = cb;
		receive_do();

		if (receive_callback_ != NULL)
			return (cancellation(this, &SSHTransportPipe::receive_cancel));

		ASSERT(receive_action_ != NULL);
		Action *a = receive_action_;
		receive_action_ = NULL;
		return (a);
	}

	/*
	 * Because this is primarily for WAN optimization we always use minimal
	 * padding and zero padding.  Quick and dirty.  Perhaps revisit later,
	 * although it makes send() asynchronous unless we add a blocking
	 * RNG interface.
	 */
	void send(Buffer *payload)
	{
		Buffer packet;
		uint8_t padding_len;
		uint32_t packet_len;

		packet_len = sizeof padding_len + payload->length();
		padding_len = 4 + (block_size_ - ((sizeof packet_len + packet_len + 4) % block_size_));
		packet_len += padding_len;

		packet_len = BigEndian::encode(packet_len);
		packet.append(&packet_len);
		packet.append(padding_len);
		packet.append(payload);
		packet.append(zero_padding, padding_len);

		if (mac_length_ != 0)
			NOTREACHED();

		payload->clear();

		produce(&packet);
	}

private:
	void consume(Buffer *in)
	{
		/* XXX XXX XXX */
		if (in->empty()) {
			if (!input_buffer_.empty())
				DEBUG(log_) << "Received EOS with data outstanding.";
			Buffer eos;
			produce(&eos);
			return;
		}

		input_buffer_.append(in);
		in->clear();

		if (state_ == GetIdentificationString) {
			HTTPProtocol::ParseStatus status;

			while (!input_buffer_.empty()) {
				Buffer line;
				status = HTTPProtocol::ExtractLine(&line, &input_buffer_);
				switch (status) {
				case HTTPProtocol::ParseSuccess:
					break;
				case HTTPProtocol::ParseFailure:
					ERROR(log_) << "Invalid line while waiting for identification string.";
					produce_error();
					return;
				case HTTPProtocol::ParseIncomplete:
					/* Wait for more.  */
					return;
				}

				if (!line.prefix("SSH-"))
					continue; /* Next line.  */

				if (!line.prefix("SSH-2.0")) {
					ERROR(log_) << "Unsupported version.";
					produce_error();
					return;
				}

				state_ = GetPacket;
				break;
			}
		}

		if (state_ == GetPacket && receive_callback_ != NULL)
			receive_do();
	}

	void receive_cancel(void)
	{
		if (receive_action_ != NULL) {
			receive_action_->cancel();
			receive_action_ = NULL;
		}

		if (receive_callback_ != NULL) {
			delete receive_callback_;
			receive_callback_ = NULL;
		}
	}

	void receive_do(void)
	{
		ASSERT(receive_action_ == NULL);
		ASSERT(receive_callback_ != NULL);

		if (state_ != GetPacket)
			return;

		while (!input_buffer_.empty()) {
			Buffer packet;
			Buffer mac;
			uint32_t packet_len;
			uint8_t padding_len;
			uint8_t msg;

			if (input_buffer_.length() <= sizeof packet_len) {
				DEBUG(log_) << "Waiting for packet length.";
				return;
			}

			input_buffer_.extract(&packet_len);
			packet_len = BigEndian::decode(packet_len);

			if (packet_len == 0) {
				ERROR(log_) << "Need to handle 0-length packet.";
				produce_error();
				return;
			}

			if (input_buffer_.length() < sizeof packet_len + packet_len + mac_length_) {
				DEBUG(log_) << "Need " << sizeof packet_len + packet_len + mac_length_ << "bytes; have " << input_buffer_.length() << ".";
				return;
			}

			input_buffer_.moveout(&packet, sizeof packet_len, packet_len);
			if (mac_length_ != 0)
				input_buffer_.moveout(&mac, 0, mac_length_);

			padding_len = packet.peek();
			packet.skip(sizeof padding_len);
			if (padding_len != 0) {
				if (packet.length() < padding_len) {
					ERROR(log_) << "Padding too large for packet.";
					produce_error();
					return;
				}
				packet.trim(padding_len);
			}

			if (packet.empty()) {
				ERROR(log_) << "Need to handle empty packet.";
				produce_error();
				return;
			}

			/*
			 * Pass by range to registered handlers for each range.
			 * Unhandled messages go to the receive_callback_, and
			 * the caller can register key exchange mechanisms,
			 * and handle (or discard) whatever they don't handle.
			 *
			 * NB: The caller could do all this, but it's assumed
			 *     that they usually have better things to do.  If
			 *     they register no handlers, they can certainly do
			 *     so by hand.
			 */
			msg = packet.peek();
			if (msg >= SSH::Message::TransportRangeBegin &&
			    msg <= SSH::Message::TransportRangeEnd) {
				DEBUG(log_) << "Using default handler for transport message.";
			} else if (msg >= SSH::Message::AlgorithmNegotiationRangeBegin &&
				   msg <= SSH::Message::AlgorithmNegotiationRangeEnd) {
				DEBUG(log_) << "Using default handler for algorithm negotiation message.";
			} else if (msg >= SSH::Message::KeyExchangeMethodRangeBegin &&
				   msg <= SSH::Message::KeyExchangeMethodRangeEnd) {
				DEBUG(log_) << "Using default handler for key exchange method message.";
			} else if (msg >= SSH::Message::UserAuthenticationGenericRangeBegin &&
				   msg <= SSH::Message::UserAuthenticationGenericRangeEnd) {
				DEBUG(log_) << "Using default handler for generic user authentication message.";
			} else if (msg >= SSH::Message::UserAuthenticationMethodRangeBegin &&
				   msg <= SSH::Message::UserAuthenticationMethodRangeEnd) {
				DEBUG(log_) << "Using default handler for user authentication method message.";
			} else if (msg >= SSH::Message::ConnectionProtocolGlobalRangeBegin &&
				   msg <= SSH::Message::ConnectionProtocolGlobalRangeEnd) {
				DEBUG(log_) << "Using default handler for generic connection protocol message.";
			} else if (msg >= SSH::Message::ConnectionChannelRangeBegin &&
				   msg <= SSH::Message::ConnectionChannelRangeEnd) {
				DEBUG(log_) << "Using default handler for connection channel message.";
			} else if (msg >= SSH::Message::ClientProtocolReservedRangeBegin &&
				   msg <= SSH::Message::ClientProtocolReservedRangeEnd) {
				DEBUG(log_) << "Using default handler for client protocol message.";
			} else if (msg >= SSH::Message::LocalExtensionRangeBegin) {
				/* Because msg is a uint8_t, it will always be <= SSH::Message::LocalExtensionRangeEnd.  */
				DEBUG(log_) << "Using default handler for local extension message.";
			} else {
				HALT(log_) << "Message in unknown range.  That's unpossible.";
			}

			receive_callback_->param(Event(Event::Done, packet));
			receive_action_ = receive_callback_->schedule();
			receive_callback_ = NULL;

			return;
		}
	}
};

class SSHConnection {
	LogHandle log_;
	Socket *peer_;
	SSHTransportPipe *pipe_;
	Action *receive_action_;
	Splice *splice_;
	Action *splice_action_;
	Action *close_action_;
public:
	SSHConnection(Socket *peer)
	: log_("/ssh/connection"),
	  peer_(peer),
	  pipe_(NULL),
	  splice_(NULL),
	  splice_action_(NULL),
	  close_action_(NULL)
	{
		pipe_ = new SSHTransportPipe();
		EventCallback *rcb = callback(this, &SSHConnection::receive_complete);
		receive_action_ = pipe_->receive(rcb);

		splice_ = new Splice(log_ + "/splice", peer_, pipe_, peer_);
		EventCallback *cb = callback(this, &SSHConnection::splice_complete);
		splice_action_ = splice_->start(cb);
	}

	~SSHConnection()
	{
		ASSERT(close_action_ == NULL);
		ASSERT(splice_action_ == NULL);
		ASSERT(splice_ == NULL);
		ASSERT(receive_action_ == NULL);
		ASSERT(pipe_ == NULL);
		ASSERT(peer_ == NULL);
	}

private:
	void receive_complete(Event e)
	{
		receive_action_->cancel();
		receive_action_ = NULL;

		switch (e.type_) {
		case Event::Done:
			break;
		default:
			ERROR(log_) << "Unexpected event while waiting for a packet: " << e;
			return;
		}

		ASSERT(!e.buffer_.empty());

		/*
		 * SSH Echo!
		 */
		pipe_->send(&e.buffer_);

		EventCallback *rcb = callback(this, &SSHConnection::receive_complete);
		receive_action_ = pipe_->receive(rcb);
	}

	void close_complete(void)
	{
		close_action_->cancel();
		close_action_ = NULL;

		ASSERT(peer_ != NULL);
		delete peer_;
		peer_ = NULL;

		delete this;
	}

	void splice_complete(Event e)
	{
		splice_action_->cancel();
		splice_action_ = NULL;

		switch (e.type_) {
		case Event::EOS:
			DEBUG(log_) << "Peer exiting normally.";
			break;
		case Event::Error:
			ERROR(log_) << "Peer exiting with error: " << e;
			break;
		default:
			ERROR(log_) << "Peer exiting with unknown event: " << e;
			break;
		}

	        ASSERT(splice_ != NULL);
		delete splice_;
		splice_ = NULL;

		if (receive_action_ != NULL) {
			INFO(log_) << "Peer exiting while waiting for a packet.";

			receive_action_->cancel();
			receive_action_ = NULL;
		}

		ASSERT(pipe_ != NULL);
		delete pipe_;
		pipe_ = NULL;

		ASSERT(close_action_ == NULL);
		SimpleCallback *cb = callback(this, &SSHConnection::close_complete);
		close_action_ = peer_->close(cb);
	}
};

class SSHServer : public SimpleServer<TCPServer> {
public:
	SSHServer(SocketAddressFamily family, const std::string& interface)
	: SimpleServer<TCPServer>("/ssh/server", family, interface)
	{ }

	~SSHServer()
	{ }

	void client_connected(Socket *client)
	{
		new SSHConnection(client);
	}
};

int
main(void)
{
	new SSHServer(SocketAddressFamilyIP, "[::]:2299");
	event_main();
}
<commit_msg>Fix.<commit_after>#include <common/endian.h>

#include <event/event_callback.h>
#include <event/event_main.h>
#include <event/event_system.h>

#include <http/http_protocol.h>

#include <io/net/tcp_server.h>

#include <io/pipe/pipe.h>
#include <io/pipe/pipe_producer.h>
#include <io/pipe/splice.h>

#include <io/socket/simple_server.h>

#include <ssh/ssh_protocol.h>

namespace {
	static uint8_t zero_padding[255];
}

class SSHTransportPipe : public PipeProducer {
	enum State {
		GetIdentificationString,
		GetPacket
	};

	State state_;
	Buffer input_buffer_;

	/* XXX These parameters are different for receive and send.  */
	size_t block_size_;
	size_t mac_length_;

	EventCallback *receive_callback_;
	Action *receive_action_;
public:
	SSHTransportPipe(void)
	: PipeProducer("/ssh/transport/pipe"),
	  state_(GetIdentificationString),
	  block_size_(8),
	  mac_length_(0),
	  receive_callback_(NULL),
	  receive_action_(NULL)
	{
		Buffer identification_string("SSH-2.0-WANProxy " + (std::string)log_ + "\r\n");
		produce(&identification_string);
	}

	~SSHTransportPipe()
	{
		ASSERT(receive_callback_ == NULL);
		ASSERT(receive_action_ == NULL);
	}

	Action *receive(EventCallback *cb)
	{
		ASSERT(receive_callback_ == NULL);
		ASSERT(receive_action_ == NULL);

		/*
		 * XXX
		 * This pattern is implemented about three different
		 * ways in the WANProxy codebase, and they are all kind
		 * of awful.  Need a better way to handle code that
		 * needs executed either on the request of the caller
		 * or when data comes in that satisfies a deferred
		 * callback to a caller.
		 */
		receive_callback_ = cb;
		receive_do();

		if (receive_callback_ != NULL)
			return (cancellation(this, &SSHTransportPipe::receive_cancel));

		ASSERT(receive_action_ != NULL);
		Action *a = receive_action_;
		receive_action_ = NULL;
		return (a);
	}

	/*
	 * Because this is primarily for WAN optimization we always use minimal
	 * padding and zero padding.  Quick and dirty.  Perhaps revisit later,
	 * although it makes send() asynchronous unless we add a blocking
	 * RNG interface.
	 */
	void send(Buffer *payload)
	{
		Buffer packet;
		uint8_t padding_len;
		uint32_t packet_len;

		packet_len = sizeof padding_len + payload->length();
		padding_len = 4 + (block_size_ - ((sizeof packet_len + packet_len + 4) % block_size_));
		packet_len += padding_len;

		packet_len = BigEndian::encode(packet_len);
		packet.append(&packet_len);
		packet.append(padding_len);
		packet.append(payload);
		packet.append(zero_padding, padding_len);

		if (mac_length_ != 0)
			NOTREACHED();

		payload->clear();

		produce(&packet);
	}

private:
	void consume(Buffer *in)
	{
		/* XXX XXX XXX */
		if (in->empty()) {
			if (!input_buffer_.empty())
				DEBUG(log_) << "Received EOS with data outstanding.";
			Buffer eos;
			produce(&eos);
			return;
		}

		input_buffer_.append(in);
		in->clear();

		if (state_ == GetIdentificationString) {
			HTTPProtocol::ParseStatus status;

			while (!input_buffer_.empty()) {
				Buffer line;
				status = HTTPProtocol::ExtractLine(&line, &input_buffer_);
				switch (status) {
				case HTTPProtocol::ParseSuccess:
					break;
				case HTTPProtocol::ParseFailure:
					ERROR(log_) << "Invalid line while waiting for identification string.";
					produce_error();
					return;
				case HTTPProtocol::ParseIncomplete:
					/* Wait for more.  */
					return;
				}

				if (!line.prefix("SSH-"))
					continue; /* Next line.  */

				if (!line.prefix("SSH-2.0")) {
					ERROR(log_) << "Unsupported version.";
					produce_error();
					return;
				}

				state_ = GetPacket;
				break;
			}
		}

		if (state_ == GetPacket && receive_callback_ != NULL)
			receive_do();
	}

	void receive_cancel(void)
	{
		if (receive_action_ != NULL) {
			receive_action_->cancel();
			receive_action_ = NULL;
		}

		if (receive_callback_ != NULL) {
			delete receive_callback_;
			receive_callback_ = NULL;
		}
	}

	void receive_do(void)
	{
		ASSERT(receive_action_ == NULL);
		ASSERT(receive_callback_ != NULL);

		if (state_ != GetPacket)
			return;

		while (!input_buffer_.empty()) {
			Buffer packet;
			Buffer mac;
			uint32_t packet_len;
			uint8_t padding_len;
			uint8_t msg;

			if (input_buffer_.length() <= sizeof packet_len) {
				DEBUG(log_) << "Waiting for packet length.";
				return;
			}

			input_buffer_.extract(&packet_len);
			packet_len = BigEndian::decode(packet_len);

			if (packet_len == 0) {
				ERROR(log_) << "Need to handle 0-length packet.";
				produce_error();
				return;
			}

			if (input_buffer_.length() < sizeof packet_len + packet_len + mac_length_) {
				DEBUG(log_) << "Need " << sizeof packet_len + packet_len + mac_length_ << "bytes; have " << input_buffer_.length() << ".";
				return;
			}

			input_buffer_.moveout(&packet, sizeof packet_len, packet_len);
			if (mac_length_ != 0)
				input_buffer_.moveout(&mac, 0, mac_length_);

			padding_len = packet.peek();
			packet.skip(sizeof padding_len);
			if (padding_len != 0) {
				if (packet.length() < padding_len) {
					ERROR(log_) << "Padding too large for packet.";
					produce_error();
					return;
				}
				packet.trim(padding_len);
			}

			if (packet.empty()) {
				ERROR(log_) << "Need to handle empty packet.";
				produce_error();
				return;
			}

			/*
			 * Pass by range to registered handlers for each range.
			 * Unhandled messages go to the receive_callback_, and
			 * the caller can register key exchange mechanisms,
			 * and handle (or discard) whatever they don't handle.
			 *
			 * NB: The caller could do all this, but it's assumed
			 *     that they usually have better things to do.  If
			 *     they register no handlers, they can certainly do
			 *     so by hand.
			 */
			msg = packet.peek();
			if (msg >= SSH::Message::TransportRangeBegin &&
			    msg <= SSH::Message::TransportRangeEnd) {
				DEBUG(log_) << "Using default handler for transport message.";
			} else if (msg >= SSH::Message::AlgorithmNegotiationRangeBegin &&
				   msg <= SSH::Message::AlgorithmNegotiationRangeEnd) {
				DEBUG(log_) << "Using default handler for algorithm negotiation message.";
			} else if (msg >= SSH::Message::KeyExchangeMethodRangeBegin &&
				   msg <= SSH::Message::KeyExchangeMethodRangeEnd) {
				DEBUG(log_) << "Using default handler for key exchange method message.";
			} else if (msg >= SSH::Message::UserAuthenticationGenericRangeBegin &&
				   msg <= SSH::Message::UserAuthenticationGenericRangeEnd) {
				DEBUG(log_) << "Using default handler for generic user authentication message.";
			} else if (msg >= SSH::Message::UserAuthenticationMethodRangeBegin &&
				   msg <= SSH::Message::UserAuthenticationMethodRangeEnd) {
				DEBUG(log_) << "Using default handler for user authentication method message.";
			} else if (msg >= SSH::Message::ConnectionProtocolGlobalRangeBegin &&
				   msg <= SSH::Message::ConnectionProtocolGlobalRangeEnd) {
				DEBUG(log_) << "Using default handler for generic connection protocol message.";
			} else if (msg >= SSH::Message::ConnectionChannelRangeBegin &&
				   msg <= SSH::Message::ConnectionChannelRangeEnd) {
				DEBUG(log_) << "Using default handler for connection channel message.";
			} else if (msg >= SSH::Message::ClientProtocolReservedRangeBegin &&
				   msg <= SSH::Message::ClientProtocolReservedRangeEnd) {
				DEBUG(log_) << "Using default handler for client protocol message.";
			} else if (msg >= SSH::Message::LocalExtensionRangeBegin) {
				/* Because msg is a uint8_t, it will always be <= SSH::Message::LocalExtensionRangeEnd.  */
				DEBUG(log_) << "Using default handler for local extension message.";
			} else {
				ASSERT(msg == 0);
				ERROR(log_) << "Message outside of protocol range received.  Passing to default handler, but not expecting much.";
			}

			receive_callback_->param(Event(Event::Done, packet));
			receive_action_ = receive_callback_->schedule();
			receive_callback_ = NULL;

			return;
		}
	}
};

class SSHConnection {
	LogHandle log_;
	Socket *peer_;
	SSHTransportPipe *pipe_;
	Action *receive_action_;
	Splice *splice_;
	Action *splice_action_;
	Action *close_action_;
public:
	SSHConnection(Socket *peer)
	: log_("/ssh/connection"),
	  peer_(peer),
	  pipe_(NULL),
	  splice_(NULL),
	  splice_action_(NULL),
	  close_action_(NULL)
	{
		pipe_ = new SSHTransportPipe();
		EventCallback *rcb = callback(this, &SSHConnection::receive_complete);
		receive_action_ = pipe_->receive(rcb);

		splice_ = new Splice(log_ + "/splice", peer_, pipe_, peer_);
		EventCallback *cb = callback(this, &SSHConnection::splice_complete);
		splice_action_ = splice_->start(cb);
	}

	~SSHConnection()
	{
		ASSERT(close_action_ == NULL);
		ASSERT(splice_action_ == NULL);
		ASSERT(splice_ == NULL);
		ASSERT(receive_action_ == NULL);
		ASSERT(pipe_ == NULL);
		ASSERT(peer_ == NULL);
	}

private:
	void receive_complete(Event e)
	{
		receive_action_->cancel();
		receive_action_ = NULL;

		switch (e.type_) {
		case Event::Done:
			break;
		default:
			ERROR(log_) << "Unexpected event while waiting for a packet: " << e;
			return;
		}

		ASSERT(!e.buffer_.empty());

		/*
		 * SSH Echo!
		 */
		pipe_->send(&e.buffer_);

		EventCallback *rcb = callback(this, &SSHConnection::receive_complete);
		receive_action_ = pipe_->receive(rcb);
	}

	void close_complete(void)
	{
		close_action_->cancel();
		close_action_ = NULL;

		ASSERT(peer_ != NULL);
		delete peer_;
		peer_ = NULL;

		delete this;
	}

	void splice_complete(Event e)
	{
		splice_action_->cancel();
		splice_action_ = NULL;

		switch (e.type_) {
		case Event::EOS:
			DEBUG(log_) << "Peer exiting normally.";
			break;
		case Event::Error:
			ERROR(log_) << "Peer exiting with error: " << e;
			break;
		default:
			ERROR(log_) << "Peer exiting with unknown event: " << e;
			break;
		}

	        ASSERT(splice_ != NULL);
		delete splice_;
		splice_ = NULL;

		if (receive_action_ != NULL) {
			INFO(log_) << "Peer exiting while waiting for a packet.";

			receive_action_->cancel();
			receive_action_ = NULL;
		}

		ASSERT(pipe_ != NULL);
		delete pipe_;
		pipe_ = NULL;

		ASSERT(close_action_ == NULL);
		SimpleCallback *cb = callback(this, &SSHConnection::close_complete);
		close_action_ = peer_->close(cb);
	}
};

class SSHServer : public SimpleServer<TCPServer> {
public:
	SSHServer(SocketAddressFamily family, const std::string& interface)
	: SimpleServer<TCPServer>("/ssh/server", family, interface)
	{ }

	~SSHServer()
	{ }

	void client_connected(Socket *client)
	{
		new SSHConnection(client);
	}
};

int
main(void)
{
	new SSHServer(SocketAddressFamilyIP, "[::]:2299");
	event_main();
}
<|endoftext|>


<commit_before>/*
 * main.cpp
 *
 *  Created on: 09.05.2014
 *      Author: trifon
 */

#include <iostream>
using namespace std;

#include "student.h"

int main() {
	Person p("Иван Иванов", "8311100123");
	p.setName("Петър Петров");
	cout << p.getID() << endl;
	p.print();

	Student s("Мария Георгиева", "1234567890", 44444, 5.5);
	s.setName("Пенка Георгиева");
	cout << s.getName() << endl;
	cout << s.getFN() << endl;
	s.print();

	Person p2 = s;
	p2.print();

	Person* pp = &s;
	cout << &s << ' ' << pp << endl;

	// !!!
	Student s2 = (Student const&)p;
	// !!! Student s2 = (Student)p;
	s2.print();

	// !!! Person p3 = s;
	Person& p3 = s;

	Student s3 = (Student const&)p3;
	s3.print();
}

<commit_msg>Тест за PaidStudent. Програмата не работи - защо?<commit_after>/*
 * main.cpp
 *
 *  Created on: 09.05.2014
 *      Author: trifon
 */

#include <iostream>
using namespace std;

#include "paid_student.h"

void paidStudentTest() {
	PaidStudent ps1, ps2("Тодор Тодоров", "9876543210", 50000, 4.25, 10000, "ФМИ"),
			    ps3 = ps2;
	ps1 = ps3;

}

int main() {
	Person p("Иван Иванов", "8311100123");
	p.setName("Петър Петров");
	cout << p.getID() << endl;
	p.print();

	Student s("Мария Георгиева", "1234567890", 44444, 5.5);
	s.setName("Пенка Георгиева");
	cout << s.getName() << endl;
	cout << s.getFN() << endl;
	s.print();

	Person p2 = s;
	p2.print();

	Person* pp = &s;
	cout << &s << ' ' << pp << endl;

	// !!!
	Student s2 = (Student const&)p;
	// !!! Student s2 = (Student)p;
	s2.print();

	// !!! Person p3 = s;
	Person& p3 = s;

	Student s3 = (Student const&)p3;
	s3.print();

	cerr << "======================" << endl;

	paidStudentTest();

	cerr << "======================" << endl;

}

<|endoftext|>