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

#ifndef DLL_STANDARD_CONV_RBM_HPP
#define DLL_STANDARD_CONV_RBM_HPP

#include "base_conf.hpp"    //The configuration helpers
#include "rbm_base.hpp"     //The base class
#include "layer_traits.hpp" //layer_traits
#include "util/checks.hpp"  //nan_check
#include "util/timers.hpp"  //auto_timer

namespace dll {

/*!
 * \brief Standard version of Convolutional Restricted Boltzmann Machine
 *
 * This follows the definition of a CRBM by Honglak Lee. This is an "abstract" class,
 * using CRTP to inject features into its children.
 */
template <typename Parent, typename Desc>
struct standard_conv_rbm : public rbm_base<Parent, Desc> {
    using desc      = Desc;
    using parent_t  = Parent;
    using this_type = standard_conv_rbm<parent_t, desc>;
    using base_type = rbm_base<parent_t, Desc>;
    using weight    = typename desc::weight;

    static constexpr const unit_type visible_unit = desc::visible_unit;
    static constexpr const unit_type hidden_unit  = desc::hidden_unit;

    static_assert(visible_unit == unit_type::BINARY || visible_unit == unit_type::GAUSSIAN,
                  "Only binary and linear visible units are supported");
    static_assert(hidden_unit == unit_type::BINARY || is_relu(hidden_unit),
                  "Only binary hidden units are supported");

    double std_gaussian = 0.2;
    double c_sigm       = 1.0;

    //Constructors

    standard_conv_rbm() {
        //Note: Convolutional RBM needs lower learning rate than standard RBM

        //Better initialization of learning rate
        base_type::learning_rate =
            visible_unit == unit_type::GAUSSIAN ? 1e-5
                                                : is_relu(hidden_unit) ? 1e-4
                                                                       : /* Only Gaussian Units needs lower rate */ 1e-3;
    }

    parent_t& as_derived() {
        return *static_cast<parent_t*>(this);
    }

    const parent_t& as_derived() const {
        return *static_cast<const parent_t*>(this);
    }

    //Utility functions

    template <typename Sample>
    void reconstruct(const Sample& items) {
        reconstruct(items, as_derived());
    }

    void display_visible_unit_activations() const {
        display_visible_unit_activations(as_derived());
    }

    void display_visible_unit_samples() const {
        display_visible_unit_samples(as_derived());
    }

    void display_hidden_unit_activations() const {
        display_hidden_unit_samples(as_derived());
    }

    void display_hidden_unit_samples() const {
        display_hidden_unit_samples(as_derived());
    }

protected:
    template <typename W>
    static void deep_fflip(W&& w_f) {
        //flip all the kernels horizontally and vertically

        for (std::size_t channel = 0; channel < etl::dim<0>(w_f); ++channel) {
            for (size_t k = 0; k < etl::dim<1>(w_f); ++k) {
                w_f(channel)(k).fflip_inplace();
            }
        }
    }

    template <typename L, typename V1, typename VCV, typename W>
    static void compute_vcv(const V1& v_a, VCV&& v_cv, W&& w) {
        dll::auto_timer timer("crbm:compute_vcv");

        static constexpr const auto NC = L::NC;

        auto w_f = etl::force_temporary(w);

        deep_fflip(w_f);

        v_cv(1) = 0;

        for (std::size_t channel = 0; channel < NC; ++channel) {
            etl::conv_2d_valid_multi(v_a(channel), w_f(channel), v_cv(0));

            v_cv(1) += v_cv(0);
        }

        nan_check_deep(v_cv);
    }

    template <typename L, typename H2, typename HCV, typename W, typename Functor>
    static void compute_hcv(const H2& h_s, HCV&& h_cv, W&& w, Functor activate) {
        dll::auto_timer timer("crbm:compute_hcv");

        static constexpr const auto K  = L::K;
        static constexpr const auto NC = L::NC;

        for (std::size_t channel = 0; channel < NC; ++channel) {
            h_cv(1) = 0.0;

            for (std::size_t k = 0; k < K; ++k) {
                h_cv(0) = etl::fast_conv_2d_full(h_s(k), w(channel)(k));
                h_cv(1) += h_cv(0);
            }

            activate(channel);
        }
    }

#ifdef ETL_MKL_MODE

    template <typename F1, typename F2>
    static void deep_pad(const F1& in, F2& out) {
        for (std::size_t outer1 = 0; outer1 < in.template dim<0>(); ++outer1) {
            for (std::size_t outer2 = 0; outer2 < in.template dim<1>(); ++outer2) {
                auto* direct = out(outer1)(outer2).memory_start();
                for (std::size_t i = 0; i < in.template dim<2>(); ++i) {
                    for (std::size_t j = 0; j < in.template dim<3>(); ++j) {
                        direct[i * out.template dim<3>() + j] = in(outer1, outer2, i, j);
                    }
                }
            }
        }
    }

    static void inplace_ifft2(std::complex<double>* memory, std::size_t m1, std::size_t m2) {
        etl::impl::blas::detail::inplace_zifft2_kernel(memory, m1, m2);
    }

    static void inplace_ifft2(std::complex<float>* memory, std::size_t m1, std::size_t m2) {
        etl::impl::blas::detail::inplace_cifft2_kernel(memory, m1, m2);
    }

    template <typename L, typename TP, typename H2, typename HCV, typename W, typename Functor>
    static void batch_compute_hcv(TP& pool, const H2& h_s, HCV&& h_cv, W&& w, Functor activate) {
        dll::auto_timer timer("crbm:batch_compute_hcv:mkl");

        static constexpr const auto Batch = layer_traits<L>::batch_size();

        static constexpr const auto K   = L::K;
        static constexpr const auto NC  = L::NC;
        static constexpr const auto NV1 = L::NV1;
        static constexpr const auto NV2 = L::NV2;

        etl::fast_dyn_matrix<std::complex<weight>, Batch, K, NV1, NV2> h_s_padded;
        etl::fast_dyn_matrix<std::complex<weight>, NC, K, NV1, NV2> w_padded;
        etl::fast_dyn_matrix<std::complex<weight>, Batch, NV1, NV2> tmp_result;

        deep_pad(h_s, h_s_padded);
        deep_pad(w, w_padded);

        h_s_padded.fft2_many_inplace();
        w_padded.fft2_many_inplace();

        maybe_parallel_foreach_n(pool, 0, Batch, [&](std::size_t batch) {
            for (std::size_t channel = 0; channel < NC; ++channel) {
                h_cv(batch)(1) = 0.0;

                for (std::size_t k = 0; k < K; ++k) {
                    tmp_result(batch) = h_s_padded(batch)(k) >> w_padded(channel)(k);

                    tmp_result(batch).ifft2_inplace();

                    for (std::size_t i = 0; i < etl::size(tmp_result(batch)); ++i) {
                        h_cv(batch)(1)[i] += tmp_result(batch)[i].real();
                    }
                }

                activate(batch, channel);
            }
        });
    }

#else

    template <typename L, typename TP, typename H2, typename HCV, typename W, typename Functor>
    static void batch_compute_hcv(TP& pool, const H2& h_s, HCV&& h_cv, W&& w, Functor activate) {
        dll::auto_timer timer("crbm:batch_compute_hcv:std");

        static constexpr const auto Batch = layer_traits<L>::batch_size();

        static constexpr const auto K  = L::K;
        static constexpr const auto NC = L::NC;

        maybe_parallel_foreach_n(pool, 0, Batch, [&](std::size_t batch) {
            for (std::size_t channel = 0; channel < NC; ++channel) {
                h_cv(batch)(1) = 0.0;

                for (std::size_t k = 0; k < K; ++k) {
                    h_cv(batch)(0) = etl::fast_conv_2d_full(h_s(batch)(k), w(channel)(k));
                    h_cv(batch)(1) += h_cv(batch)(0);
                }

                activate(batch, channel);
            }
        });
    }

#endif

    template <typename L, typename TP, typename V1, typename VCV, typename W, typename Functor>
    static void batch_compute_vcv(TP& pool, const V1& v_a, VCV&& v_cv, W&& w, Functor activate) {
        dll::auto_timer timer("crbm:batch_compute_vcv");

        static constexpr const auto Batch = layer_traits<L>::batch_size();

        static constexpr const auto NC = L::NC;

        maybe_parallel_foreach_n(pool, 0, Batch, [&](std::size_t batch) {
            etl::conv_2d_valid_multi_flipped(v_a(batch)(0), w(0), v_cv(batch)(1));

            for (std::size_t channel = 1; channel < NC; ++channel) {
                etl::conv_2d_valid_multi_flipped(v_a(batch)(channel), w(channel), v_cv(batch)(0));

                v_cv(batch)(1) += v_cv(batch)(0);
            }

            activate(batch);
        });
    }

private:
    //Since the sub classes do not have the same fields, it is not possible
    //to put the fields in standard_rbm, therefore, it is necessary to use template
    //functions to implement the details

    template <typename Sample>
    static void reconstruct(const Sample& items, parent_t& rbm) {
        cpp_assert(items.size() == parent_t::input_size(), "The size of the training sample must match visible units");

        cpp::stop_watch<> watch;

        //Set the state of the visible units
        rbm.v1 = items;

        rbm.activate_hidden(rbm.h1_a, rbm.h1_s, rbm.v1, rbm.v1);

        rbm.activate_visible(rbm.h1_a, rbm.h1_s, rbm.v2_a, rbm.v2_s);
        rbm.activate_hidden(rbm.h2_a, rbm.h2_s, rbm.v2_a, rbm.v2_s);

        std::cout << "Reconstruction took " << watch.elapsed() << "ms" << std::endl;
    }

    static void display_visible_unit_activations(const parent_t& rbm) {
        for (std::size_t channel = 0; channel < parent_t::NC; ++channel) {
            std::cout << "Channel " << channel << std::endl;

            for (size_t i = 0; i < parent_t::NV; ++i) {
                for (size_t j = 0; j < parent_t::NV; ++j) {
                    std::cout << rbm.v2_a(channel, i, j) << " ";
                }
                std::cout << std::endl;
            }
        }
    }

    static void display_visible_unit_samples(const parent_t& rbm) {
        for (std::size_t channel = 0; channel < parent_t::NC; ++channel) {
            std::cout << "Channel " << channel << std::endl;

            for (size_t i = 0; i < parent_t::NV; ++i) {
                for (size_t j = 0; j < parent_t::NV; ++j) {
                    std::cout << rbm.v2_s(channel, i, j) << " ";
                }
                std::cout << std::endl;
            }
        }
    }

    static void display_hidden_unit_activations(const parent_t& rbm) {
        for (size_t k = 0; k < parent_t::K; ++k) {
            for (size_t i = 0; i < parent_t::NV; ++i) {
                for (size_t j = 0; j < parent_t::NV; ++j) {
                    std::cout << rbm.h2_a(k)(i, j) << " ";
                }
                std::cout << std::endl;
            }
            std::cout << std::endl
                      << std::endl;
        }
    }

    static void display_hidden_unit_samples(const parent_t& rbm) {
        for (size_t k = 0; k < parent_t::K; ++k) {
            for (size_t i = 0; i < parent_t::NV; ++i) {
                for (size_t j = 0; j < parent_t::NV; ++j) {
                    std::cout << rbm.h2_s(k)(i, j) << " ";
                }
                std::cout << std::endl;
            }
            std::cout << std::endl
                      << std::endl;
        }
    }
};

} //end of dll namespace

#endif
<commit_msg>Remove old code<commit_after>//=======================================================================
// Copyright (c) 2014-2016 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#ifndef DLL_STANDARD_CONV_RBM_HPP
#define DLL_STANDARD_CONV_RBM_HPP

#include "base_conf.hpp"    //The configuration helpers
#include "rbm_base.hpp"     //The base class
#include "layer_traits.hpp" //layer_traits
#include "util/checks.hpp"  //nan_check
#include "util/timers.hpp"  //auto_timer

namespace dll {

/*!
 * \brief Standard version of Convolutional Restricted Boltzmann Machine
 *
 * This follows the definition of a CRBM by Honglak Lee. This is an "abstract" class,
 * using CRTP to inject features into its children.
 */
template <typename Parent, typename Desc>
struct standard_conv_rbm : public rbm_base<Parent, Desc> {
    using desc      = Desc;
    using parent_t  = Parent;
    using this_type = standard_conv_rbm<parent_t, desc>;
    using base_type = rbm_base<parent_t, Desc>;
    using weight    = typename desc::weight;

    static constexpr const unit_type visible_unit = desc::visible_unit;
    static constexpr const unit_type hidden_unit  = desc::hidden_unit;

    static_assert(visible_unit == unit_type::BINARY || visible_unit == unit_type::GAUSSIAN,
                  "Only binary and linear visible units are supported");
    static_assert(hidden_unit == unit_type::BINARY || is_relu(hidden_unit),
                  "Only binary hidden units are supported");

    double std_gaussian = 0.2;
    double c_sigm       = 1.0;

    //Constructors

    standard_conv_rbm() {
        //Note: Convolutional RBM needs lower learning rate than standard RBM

        //Better initialization of learning rate
        base_type::learning_rate =
            visible_unit == unit_type::GAUSSIAN ? 1e-5
                                                : is_relu(hidden_unit) ? 1e-4
                                                                       : /* Only Gaussian Units needs lower rate */ 1e-3;
    }

    parent_t& as_derived() {
        return *static_cast<parent_t*>(this);
    }

    const parent_t& as_derived() const {
        return *static_cast<const parent_t*>(this);
    }

    //Utility functions

    template <typename Sample>
    void reconstruct(const Sample& items) {
        reconstruct(items, as_derived());
    }

    void display_visible_unit_activations() const {
        display_visible_unit_activations(as_derived());
    }

    void display_visible_unit_samples() const {
        display_visible_unit_samples(as_derived());
    }

    void display_hidden_unit_activations() const {
        display_hidden_unit_samples(as_derived());
    }

    void display_hidden_unit_samples() const {
        display_hidden_unit_samples(as_derived());
    }

protected:
    template <typename W>
    static void deep_fflip(W&& w_f) {
        //flip all the kernels horizontally and vertically

        for (std::size_t channel = 0; channel < etl::dim<0>(w_f); ++channel) {
            for (size_t k = 0; k < etl::dim<1>(w_f); ++k) {
                w_f(channel)(k).fflip_inplace();
            }
        }
    }

    template <typename L, typename V1, typename VCV, typename W>
    static void compute_vcv(const V1& v_a, VCV&& v_cv, W&& w) {
        dll::auto_timer timer("crbm:compute_vcv");

        static constexpr const auto NC = L::NC;

        auto w_f = etl::force_temporary(w);

        deep_fflip(w_f);

        v_cv(1) = 0;

        for (std::size_t channel = 0; channel < NC; ++channel) {
            etl::conv_2d_valid_multi(v_a(channel), w_f(channel), v_cv(0));

            v_cv(1) += v_cv(0);
        }

        nan_check_deep(v_cv);
    }

    template <typename L, typename H2, typename HCV, typename W, typename Functor>
    static void compute_hcv(const H2& h_s, HCV&& h_cv, W&& w, Functor activate) {
        dll::auto_timer timer("crbm:compute_hcv");

        static constexpr const auto K  = L::K;
        static constexpr const auto NC = L::NC;

        for (std::size_t channel = 0; channel < NC; ++channel) {
            h_cv(1) = 0.0;

            for (std::size_t k = 0; k < K; ++k) {
                h_cv(0) = etl::fast_conv_2d_full(h_s(k), w(channel)(k));
                h_cv(1) += h_cv(0);
            }

            activate(channel);
        }
    }

#ifdef ETL_MKL_MODE

    template <typename F1, typename F2>
    static void deep_pad(const F1& in, F2& out) {
        for (std::size_t outer1 = 0; outer1 < in.template dim<0>(); ++outer1) {
            for (std::size_t outer2 = 0; outer2 < in.template dim<1>(); ++outer2) {
                auto* direct = out(outer1)(outer2).memory_start();
                for (std::size_t i = 0; i < in.template dim<2>(); ++i) {
                    for (std::size_t j = 0; j < in.template dim<3>(); ++j) {
                        direct[i * out.template dim<3>() + j] = in(outer1, outer2, i, j);
                    }
                }
            }
        }
    }

    template <typename L, typename TP, typename H2, typename HCV, typename W, typename Functor>
    static void batch_compute_hcv(TP& pool, const H2& h_s, HCV&& h_cv, W&& w, Functor activate) {
        dll::auto_timer timer("crbm:batch_compute_hcv:mkl");

        static constexpr const auto Batch = layer_traits<L>::batch_size();

        static constexpr const auto K   = L::K;
        static constexpr const auto NC  = L::NC;
        static constexpr const auto NV1 = L::NV1;
        static constexpr const auto NV2 = L::NV2;

        etl::fast_dyn_matrix<std::complex<weight>, Batch, K, NV1, NV2> h_s_padded;
        etl::fast_dyn_matrix<std::complex<weight>, NC, K, NV1, NV2> w_padded;
        etl::fast_dyn_matrix<std::complex<weight>, Batch, NV1, NV2> tmp_result;

        deep_pad(h_s, h_s_padded);
        deep_pad(w, w_padded);

        h_s_padded.fft2_many_inplace();
        w_padded.fft2_many_inplace();

        maybe_parallel_foreach_n(pool, 0, Batch, [&](std::size_t batch) {
            for (std::size_t channel = 0; channel < NC; ++channel) {
                h_cv(batch)(1) = 0.0;

                for (std::size_t k = 0; k < K; ++k) {
                    tmp_result(batch) = h_s_padded(batch)(k) >> w_padded(channel)(k);

                    tmp_result(batch).ifft2_inplace();

                    for (std::size_t i = 0; i < etl::size(tmp_result(batch)); ++i) {
                        h_cv(batch)(1)[i] += tmp_result(batch)[i].real();
                    }
                }

                activate(batch, channel);
            }
        });
    }

#else

    template <typename L, typename TP, typename H2, typename HCV, typename W, typename Functor>
    static void batch_compute_hcv(TP& pool, const H2& h_s, HCV&& h_cv, W&& w, Functor activate) {
        dll::auto_timer timer("crbm:batch_compute_hcv:std");

        static constexpr const auto Batch = layer_traits<L>::batch_size();

        static constexpr const auto K  = L::K;
        static constexpr const auto NC = L::NC;

        maybe_parallel_foreach_n(pool, 0, Batch, [&](std::size_t batch) {
            for (std::size_t channel = 0; channel < NC; ++channel) {
                h_cv(batch)(1) = 0.0;

                for (std::size_t k = 0; k < K; ++k) {
                    h_cv(batch)(0) = etl::fast_conv_2d_full(h_s(batch)(k), w(channel)(k));
                    h_cv(batch)(1) += h_cv(batch)(0);
                }

                activate(batch, channel);
            }
        });
    }

#endif

    template <typename L, typename TP, typename V1, typename VCV, typename W, typename Functor>
    static void batch_compute_vcv(TP& pool, const V1& v_a, VCV&& v_cv, W&& w, Functor activate) {
        dll::auto_timer timer("crbm:batch_compute_vcv");

        static constexpr const auto Batch = layer_traits<L>::batch_size();

        static constexpr const auto NC = L::NC;

        maybe_parallel_foreach_n(pool, 0, Batch, [&](std::size_t batch) {
            etl::conv_2d_valid_multi_flipped(v_a(batch)(0), w(0), v_cv(batch)(1));

            for (std::size_t channel = 1; channel < NC; ++channel) {
                etl::conv_2d_valid_multi_flipped(v_a(batch)(channel), w(channel), v_cv(batch)(0));

                v_cv(batch)(1) += v_cv(batch)(0);
            }

            activate(batch);
        });
    }

private:
    //Since the sub classes do not have the same fields, it is not possible
    //to put the fields in standard_rbm, therefore, it is necessary to use template
    //functions to implement the details

    template <typename Sample>
    static void reconstruct(const Sample& items, parent_t& rbm) {
        cpp_assert(items.size() == parent_t::input_size(), "The size of the training sample must match visible units");

        cpp::stop_watch<> watch;

        //Set the state of the visible units
        rbm.v1 = items;

        rbm.activate_hidden(rbm.h1_a, rbm.h1_s, rbm.v1, rbm.v1);

        rbm.activate_visible(rbm.h1_a, rbm.h1_s, rbm.v2_a, rbm.v2_s);
        rbm.activate_hidden(rbm.h2_a, rbm.h2_s, rbm.v2_a, rbm.v2_s);

        std::cout << "Reconstruction took " << watch.elapsed() << "ms" << std::endl;
    }

    static void display_visible_unit_activations(const parent_t& rbm) {
        for (std::size_t channel = 0; channel < parent_t::NC; ++channel) {
            std::cout << "Channel " << channel << std::endl;

            for (size_t i = 0; i < parent_t::NV; ++i) {
                for (size_t j = 0; j < parent_t::NV; ++j) {
                    std::cout << rbm.v2_a(channel, i, j) << " ";
                }
                std::cout << std::endl;
            }
        }
    }

    static void display_visible_unit_samples(const parent_t& rbm) {
        for (std::size_t channel = 0; channel < parent_t::NC; ++channel) {
            std::cout << "Channel " << channel << std::endl;

            for (size_t i = 0; i < parent_t::NV; ++i) {
                for (size_t j = 0; j < parent_t::NV; ++j) {
                    std::cout << rbm.v2_s(channel, i, j) << " ";
                }
                std::cout << std::endl;
            }
        }
    }

    static void display_hidden_unit_activations(const parent_t& rbm) {
        for (size_t k = 0; k < parent_t::K; ++k) {
            for (size_t i = 0; i < parent_t::NV; ++i) {
                for (size_t j = 0; j < parent_t::NV; ++j) {
                    std::cout << rbm.h2_a(k)(i, j) << " ";
                }
                std::cout << std::endl;
            }
            std::cout << std::endl
                      << std::endl;
        }
    }

    static void display_hidden_unit_samples(const parent_t& rbm) {
        for (size_t k = 0; k < parent_t::K; ++k) {
            for (size_t i = 0; i < parent_t::NV; ++i) {
                for (size_t j = 0; j < parent_t::NV; ++j) {
                    std::cout << rbm.h2_s(k)(i, j) << " ";
                }
                std::cout << std::endl;
            }
            std::cout << std::endl
                      << std::endl;
        }
    }
};

} //end of dll namespace

#endif
<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2014-2015 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 <algorithm>

#include "cpp_utils/assert.hpp"
#include "cpp_utils/tmp.hpp"

#include "etl/traits_lite.hpp"

//Get the implementations
#include "etl/impl/pooling.hpp"

namespace etl {

template<typename T, std::size_t C1, std::size_t C2, template<typename...> class Impl>
struct basic_pool_2d_expr {
    static_assert(C1 > 0, "C1 must be greater than 0");
    static_assert(C2 > 0, "C2 must be greater than 0");

    using this_type = basic_pool_2d_expr<T, C1, C2, Impl>;

    template<typename A, std::size_t DD>
    static constexpr std::size_t dim(){
        return DD == 0 ? decay_traits<A>::template dim<0>() / C1
                       : decay_traits<A>::template dim<1>() / C2;
    }

    template<typename A, class Enable = void>
    struct result_type_builder {
        using type = dyn_matrix<value_t<A>, 2>;
    };

    template<typename A>
    struct result_type_builder<A, std::enable_if_t<all_fast<A>::value>> {
        using type = fast_dyn_matrix<value_t<A>, this_type::template dim<A, 0>(), this_type::template dim<A, 1>()>;
    };

    template<typename A>
    using result_type = typename result_type_builder<A>::type;

    template<typename A, cpp_enable_if(all_fast<A>::value)>
    static result_type<A>* allocate(A&& /*a*/){
        return new result_type<A>();
    }

    template<typename A, cpp_disable_if(all_fast<A>::value)>
    static result_type<A>* allocate(A&& a){
        return new result_type<A>(etl::dim<0>(a) / C2, etl::dim<1>(a) / C2);
    }

    template<typename A, typename C>
    static void apply(A&& a, C&& c){
        static_assert(all_etl_expr<A, C>::value, "pool_2d only supported for ETL expressions");
        static_assert(decay_traits<A>::dimensions() == 2 && decay_traits<C>::dimensions() == 2, "pool_2d needs 2D matrices");

        Impl<decltype(make_temporary(std::forward<A>(a))), C>::template apply<C1, C2>(
            make_temporary(std::forward<A>(a)),
            std::forward<C>(c));
    }

    static std::string desc() noexcept {
        return "pool_2d";
    }

    template<typename A>
    static std::size_t dim(const A& a, std::size_t d){
        if(d == 0){
            return etl::dim<0>(a) / C1;
        } else {
            return etl::dim<1>(a) / C2;
        }
    }

    template<typename A>
    static std::size_t size(const A& a){
        return (etl::dim<0>(a) / C1) * (etl::dim<1>(a) / C2);
    }

    template<typename A>
    static constexpr std::size_t size(){
        return this_type::template dim<A, 0>() * this_type::template dim<A, 1>();
    }

    static constexpr std::size_t dimensions(){
        return 2;
    }
};

//Max Pool 2D

template<typename T, std::size_t C1, std::size_t C2>
using max_pool_2d_expr = basic_pool_2d_expr<T, C1, C2, impl::max_pool_2d>;

template<typename T, std::size_t C1, std::size_t C2>
using avg_pool_2d_expr = basic_pool_2d_expr<T, C1, C2, impl::avg_pool_2d>;

template<typename T, std::size_t C1, std::size_t C2, std::size_t C3, template<typename...> class Impl>
struct basic_pool_3d_expr {
    static_assert(C1 > 0, "C1 must be greater than 0");
    static_assert(C2 > 0, "C2 must be greater than 0");
    static_assert(C3 > 0, "C3 must be greater than 0");

    using this_type = basic_pool_3d_expr<T, C1, C2, C3, Impl>;

    template<typename A, std::size_t DD>
    static constexpr std::size_t dim(){
        return   DD == 0 ? decay_traits<A>::template dim<0>() / C1
               : DD == 1 ? decay_traits<A>::template dim<1>() / C2
                         : decay_traits<A>::template dim<2>() / C3;
    }

    template<typename A, class Enable = void>
    struct result_type_builder {
        using type = dyn_matrix<value_t<A>, 3>;
    };

    template<typename A>
    struct result_type_builder<A, std::enable_if_t<all_fast<A>::value>> {
        using type = fast_dyn_matrix<value_t<A>, this_type::template dim<A, 0>(), this_type::template dim<A, 1>(), this_type::template dim<A, 2>()>;
    };

    template<typename A>
    using result_type = typename result_type_builder<A>::type;

    template<typename A, cpp_enable_if(all_fast<A>::value)>
    static result_type<A>* allocate(A&& /*a*/){
        return new result_type<A>();
    }

    template<typename A, cpp_disable_if(all_fast<A>::value)>
    static result_type<A>* allocate(A&& a){
        return new result_type<A>(etl::dim<0>(a) / C2, etl::dim<1>(a) / C2, etl::dim<2>(a) / C3);
    }

    template<typename A, typename C>
    static void apply(A&& a, C&& c){
        static_assert(all_etl_expr<A, C>::value, "pool_3d only supported for ETL expressions");
        static_assert(decay_traits<A>::dimensions() == 3 && decay_traits<C>::dimensions() == 3, "pool_3d needs 3D matrices");

        Impl<decltype(make_temporary(std::forward<A>(a))), C>::template apply<C1, C2, C3>(
            make_temporary(std::forward<A>(a)),
            std::forward<C>(c));
    }

    static std::string desc() noexcept {
        return "pool_3d";
    }

    template<typename A>
    static std::size_t dim(const A& a, std::size_t d){
        if(d == 0){
            return etl::dim<0>(a) / C1;
        } else if(d == 1){
            return etl::dim<1>(a) / C2;
        } else {
            return etl::dim<2>(a) / C3;
        }
    }

    template<typename A>
    static std::size_t size(const A& a){
        return (etl::dim<0>(a) / C1) * (etl::dim<1>(a) / C2) * (etl::dim<2>(a) / C3);
    }

    template<typename A>
    static constexpr std::size_t size(){
        return this_type::template dim<A, 0>() * this_type::template dim<A, 1>() * this_type::template dim<A, 2>();
    }

    static constexpr std::size_t dimensions(){
        return 3;
    }
};

//Max Pool 2D

template<typename T, std::size_t C1, std::size_t C2, std::size_t C3>
using max_pool_3d_expr = basic_pool_3d_expr<T, C1, C2, C3, impl::max_pool_3d>;

template<typename T, std::size_t C1, std::size_t C2, std::size_t C3>
using avg_pool_3d_expr = basic_pool_3d_expr<T, C1, C2, C3, impl::avg_pool_3d>;

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

/*!
 * \file fft_expr.hpp
 * \brief Contains the pooling expressions.
*/

#pragma once

#include <algorithm>

#include "cpp_utils/assert.hpp"
#include "cpp_utils/tmp.hpp"

#include "etl/traits_lite.hpp"

//Get the implementations
#include "etl/impl/pooling.hpp"

namespace etl {

/*!
 * \brief Base class for all 2D pooling expressions
 */
template<typename T, std::size_t C1, std::size_t C2, template<typename...> class Impl>
struct basic_pool_2d_expr {
    static_assert(C1 > 0, "C1 must be greater than 0");
    static_assert(C2 > 0, "C2 must be greater than 0");

    using this_type = basic_pool_2d_expr<T, C1, C2, Impl>;

    template<typename A, std::size_t DD>
    static constexpr std::size_t dim(){
        return DD == 0 ? decay_traits<A>::template dim<0>() / C1
                       : decay_traits<A>::template dim<1>() / C2;
    }

    template<typename A, class Enable = void>
    struct result_type_builder {
        using type = dyn_matrix<value_t<A>, 2>;
    };

    template<typename A>
    struct result_type_builder<A, std::enable_if_t<all_fast<A>::value>> {
        using type = fast_dyn_matrix<value_t<A>, this_type::template dim<A, 0>(), this_type::template dim<A, 1>()>;
    };

    template<typename A>
    using result_type = typename result_type_builder<A>::type;

    template<typename A, cpp_enable_if(all_fast<A>::value)>
    static result_type<A>* allocate(A&& /*a*/){
        return new result_type<A>();
    }

    template<typename A, cpp_disable_if(all_fast<A>::value)>
    static result_type<A>* allocate(A&& a){
        return new result_type<A>(etl::dim<0>(a) / C2, etl::dim<1>(a) / C2);
    }

    template<typename A, typename C>
    static void apply(A&& a, C&& c){
        static_assert(all_etl_expr<A, C>::value, "pool_2d only supported for ETL expressions");
        static_assert(decay_traits<A>::dimensions() == 2 && decay_traits<C>::dimensions() == 2, "pool_2d needs 2D matrices");

        Impl<decltype(make_temporary(std::forward<A>(a))), C>::template apply<C1, C2>(
            make_temporary(std::forward<A>(a)),
            std::forward<C>(c));
    }

    static std::string desc() noexcept {
        return "pool_2d";
    }

    template<typename A>
    static std::size_t dim(const A& a, std::size_t d){
        if(d == 0){
            return etl::dim<0>(a) / C1;
        } else {
            return etl::dim<1>(a) / C2;
        }
    }

    template<typename A>
    static std::size_t size(const A& a){
        return (etl::dim<0>(a) / C1) * (etl::dim<1>(a) / C2);
    }

    template<typename A>
    static constexpr std::size_t size(){
        return this_type::template dim<A, 0>() * this_type::template dim<A, 1>();
    }

    static constexpr std::size_t dimensions(){
        return 2;
    }
};

//Max Pool 2D

template<typename T, std::size_t C1, std::size_t C2>
using max_pool_2d_expr = basic_pool_2d_expr<T, C1, C2, impl::max_pool_2d>;

template<typename T, std::size_t C1, std::size_t C2>
using avg_pool_2d_expr = basic_pool_2d_expr<T, C1, C2, impl::avg_pool_2d>;

/*!
 * \brief Base class for all 3D pooling expressions
 */
template<typename T, std::size_t C1, std::size_t C2, std::size_t C3, template<typename...> class Impl>
struct basic_pool_3d_expr {
    static_assert(C1 > 0, "C1 must be greater than 0");
    static_assert(C2 > 0, "C2 must be greater than 0");
    static_assert(C3 > 0, "C3 must be greater than 0");

    using this_type = basic_pool_3d_expr<T, C1, C2, C3, Impl>;

    template<typename A, std::size_t DD>
    static constexpr std::size_t dim(){
        return   DD == 0 ? decay_traits<A>::template dim<0>() / C1
               : DD == 1 ? decay_traits<A>::template dim<1>() / C2
                         : decay_traits<A>::template dim<2>() / C3;
    }

    template<typename A, class Enable = void>
    struct result_type_builder {
        using type = dyn_matrix<value_t<A>, 3>;
    };

    template<typename A>
    struct result_type_builder<A, std::enable_if_t<all_fast<A>::value>> {
        using type = fast_dyn_matrix<value_t<A>, this_type::template dim<A, 0>(), this_type::template dim<A, 1>(), this_type::template dim<A, 2>()>;
    };

    template<typename A>
    using result_type = typename result_type_builder<A>::type;

    template<typename A, cpp_enable_if(all_fast<A>::value)>
    static result_type<A>* allocate(A&& /*a*/){
        return new result_type<A>();
    }

    template<typename A, cpp_disable_if(all_fast<A>::value)>
    static result_type<A>* allocate(A&& a){
        return new result_type<A>(etl::dim<0>(a) / C2, etl::dim<1>(a) / C2, etl::dim<2>(a) / C3);
    }

    template<typename A, typename C>
    static void apply(A&& a, C&& c){
        static_assert(all_etl_expr<A, C>::value, "pool_3d only supported for ETL expressions");
        static_assert(decay_traits<A>::dimensions() == 3 && decay_traits<C>::dimensions() == 3, "pool_3d needs 3D matrices");

        Impl<decltype(make_temporary(std::forward<A>(a))), C>::template apply<C1, C2, C3>(
            make_temporary(std::forward<A>(a)),
            std::forward<C>(c));
    }

    static std::string desc() noexcept {
        return "pool_3d";
    }

    template<typename A>
    static std::size_t dim(const A& a, std::size_t d){
        if(d == 0){
            return etl::dim<0>(a) / C1;
        } else if(d == 1){
            return etl::dim<1>(a) / C2;
        } else {
            return etl::dim<2>(a) / C3;
        }
    }

    template<typename A>
    static std::size_t size(const A& a){
        return (etl::dim<0>(a) / C1) * (etl::dim<1>(a) / C2) * (etl::dim<2>(a) / C3);
    }

    template<typename A>
    static constexpr std::size_t size(){
        return this_type::template dim<A, 0>() * this_type::template dim<A, 1>() * this_type::template dim<A, 2>();
    }

    static constexpr std::size_t dimensions(){
        return 3;
    }
};

//Max Pool 2D

template<typename T, std::size_t C1, std::size_t C2, std::size_t C3>
using max_pool_3d_expr = basic_pool_3d_expr<T, C1, C2, C3, impl::max_pool_3d>;

template<typename T, std::size_t C1, std::size_t C2, std::size_t C3>
using avg_pool_3d_expr = basic_pool_3d_expr<T, C1, C2, C3, impl::avg_pool_3d>;

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


<commit_before>/*
DisplayController.h - Library for Controlling a 14x28 bits FlipDot display sign using two FP2800A.
Created by Antonio Carioca, March 3, 2014.
*/

//#include "Arduino.h"

//#include <avr/pgmspace.h>
//#include "application.h"
#include "mark-iv-flip-dot-display-sign-14x28-controller.h"

/* CONSTANTS */
//const int DISPLAY_SIZE = 4;
const int DISPLAY_PIXEL_WIDTH = 28;
const int DISPLAY_PIXEL_HEIGHT = 14;
const int DISPLAY_SUBPANEL_QTY = 2;

//=== F O N T ===
// Font courtesy of aspro648
// coden taken from
// http://www.instructables.com/files/orig/FQC/A1CY/H5EW79JK/FQCA1CYH5EW79JK.txt
// The @ will display as space character.
// NOTE: MOVING ALL THE ARRAY BELOW TO PROGMEM

//DotDisplay::DotDisplay(int dataPin, int clockPin, int latchPin, int enableSubPanel1Pin, int enableSubPanel2Pin, int fontWidth, int fontHeight, prog_uchar fonteParam[][5]){
DotDisplay::DotDisplay(int dataPin, int clockPin, int latchPin,  int enableSubPanel1Pin, int enableSubPanel2Pin, int fontWidth, int fontHeight, byte fonteParam[][5]){

	pinMode(dataPin, OUTPUT);
	pinMode(clockPin, OUTPUT);
	pinMode(latchPin, OUTPUT);
	pinMode(enableSubPanel1Pin, OUTPUT);
	pinMode(enableSubPanel2Pin, OUTPUT);
	//disable FP2800A's
	digitalWrite(enableSubPanel1Pin, LOW);
	digitalWrite(enableSubPanel2Pin, LOW);

	_dataPin = dataPin;
	_clockPin = clockPin;
	_latchPin = latchPin;
	_enableSubPanel1Pin = enableSubPanel1Pin;
	_enableSubPanel2Pin = enableSubPanel2Pin;
	_fontWidth = fontWidth;
	_fontHeight = fontHeight;
	_fonteParam = fonteParam;

	//_maxNumRows = floor((DISPLAY_PIXEL_HEIGHT+1)/(_fontHeight));
	_maxNumRows = (int)((DISPLAY_PIXEL_HEIGHT+1)/(_fontHeight));
	//_maxRowLength = floor((DISPLAY_PIXEL_WIDTH * DISPLAY_SUBPANEL_QTY+1) / (_fontWidth+1));
	_maxRowLength = (int)((DISPLAY_PIXEL_WIDTH * DISPLAY_SUBPANEL_QTY+1) / (_fontWidth+1));
	_maxMessageLength = _maxRowLength * _maxNumRows;

}
/*
void DotDisplay::setSerial(HardwareSerial* hwPrint){
	printer = hwPrint; //operate on the address of print
	if(printer) {
		printer->begin(9600);
	}
}
*/

void DotDisplay::setDot(byte col, byte row, bool on){

	//accidentally reversed two data pins, so reversing back on the code here
	//on = !on;

	//2 pins - Data
	//5 pins - Column
	//4 pins - Rows

	//4 pins - Enable FP2800A (4 subpanels)
	byte subPanel = 1;
	//disable FP2800A's
	digitalWrite(_enableSubPanel1Pin, LOW);
	digitalWrite(_enableSubPanel2Pin, LOW);

	//enables next sunpanel
	if(col>=DISPLAY_PIXEL_WIDTH){
		//subPanel =  floor(col / DISPLAY_PIXEL_WIDTH)+1;
		subPanel =  (int)(col / DISPLAY_PIXEL_WIDTH)+1;
		col=col-DISPLAY_PIXEL_WIDTH;
	}

	/*
	if(printer) {
	printer->print("col: ");
	printer->print(col);
	printer->print(", ");
	printer->print("subPanel: ");
	printer->println(subPanel);
	}
	*/

	// IGNOREx4 + ROWx4 + IGNOREx1 + COLUMNx5 + DATAx2
	byte dataPins = on?1:2;
	byte colFirstThreeDigits = (col % 7)+1;
	//byte colLastTwoDigits = floor(col/7);
	byte colLastTwoDigits = (int)(col/7);
	byte colByte = colFirstThreeDigits | (colLastTwoDigits << 3);
	byte rowFirstThreeDigits = (row % 7)+1;
	byte rowLastDigit = row<7;
	byte rowByte = rowFirstThreeDigits | (rowLastDigit << 3);
	byte firstbyte = (dataPins) | (colByte << 2);
	byte secondbyte = rowByte;

	digitalWrite(_latchPin, LOW);
	shiftOut(_dataPin, _clockPin, LSBFIRST, firstbyte);
	shiftOut(_dataPin, _clockPin, LSBFIRST, secondbyte);
	digitalWrite(_latchPin, HIGH);
	//delay(1);

	//pulse the FP2800A's enable pins
	if(subPanel == 1){
		digitalWrite(_enableSubPanel1Pin, HIGH);
		delay(1);
		digitalWrite(_enableSubPanel1Pin, LOW);
	} else if (subPanel == 2) {
		digitalWrite(_enableSubPanel2Pin, HIGH);
		delay(1);
		digitalWrite(_enableSubPanel2Pin, LOW);
	}
}

//void DotDisplay::updateDisplay(char *textMessage){
void DotDisplay::updateDisplay(char textMessage[], char log[]){
	int currentColumn = 0;
	int currentRow = 0;

	strcpy(log,"");

	//goes through all characters
	for (int ch = 0; ch < (_maxMessageLength);ch++){
		//get a character from the message
		int alphabetIndex = textMessage[ch] - ' '; //Subtract '@' so we get a number

		//Serial.println(alphabetIndex);
		if ((alphabetIndex < 0) or (ch >=strlen(textMessage))) alphabetIndex=0;

		//push it to the next row if necessary
		if((currentColumn + _fontWidth) > (DISPLAY_PIXEL_WIDTH * DISPLAY_SUBPANEL_QTY)){
			currentColumn=0;
			currentRow=currentRow+_fontHeight;
		}

		//set all the bits in the next _fontWidth columns on the display
		for(byte col = currentColumn; col<(currentColumn+_fontWidth); col++){

			byte calculatedColumn = (col)%(_fontWidth+1);
			//for(byte row = 0; row < _fontHeight; row++)
			int characterRow = 0;
			for(byte row = currentRow; row < (currentRow + _fontHeight); row++){
				//bool isOn = bitRead(pgm_read_byte(&(_fonteParam[alphabetIndex][calculatedColumn])),6-characterRow);
				bool isOn = bitRead((byte)_fonteParam[alphabetIndex][calculatedColumn],6-row);//this index is needed as we are going from back to front

				setDot(col, row, isOn);
				/*
				if(printer) {
					printer->print(isOn);
				}
				*/
				strcat(log,isOn);

				characterRow++;
			}
			/*
			if(printer) {
				printer->println("");
			}
			*/
			strcat(log,"");
		}
		/*
		if(printer) {
			printer->println("*******");
		}
		*/
		strcat(log,"*********");

		currentColumn = currentColumn+(_fontWidth+1);
	}
}
<commit_msg>Fixing debug options<commit_after>/*
DisplayController.h - Library for Controlling a 14x28 bits FlipDot display sign using two FP2800A.
Created by Antonio Carioca, March 3, 2014.
*/

//#include "Arduino.h"

//#include <avr/pgmspace.h>
//#include "application.h"
#include "mark-iv-flip-dot-display-sign-14x28-controller.h"

/* CONSTANTS */
//const int DISPLAY_SIZE = 4;
const int DISPLAY_PIXEL_WIDTH = 28;
const int DISPLAY_PIXEL_HEIGHT = 14;
const int DISPLAY_SUBPANEL_QTY = 2;

//=== F O N T ===
// Font courtesy of aspro648
// coden taken from
// http://www.instructables.com/files/orig/FQC/A1CY/H5EW79JK/FQCA1CYH5EW79JK.txt
// The @ will display as space character.
// NOTE: MOVING ALL THE ARRAY BELOW TO PROGMEM

//DotDisplay::DotDisplay(int dataPin, int clockPin, int latchPin, int enableSubPanel1Pin, int enableSubPanel2Pin, int fontWidth, int fontHeight, prog_uchar fonteParam[][5]){
DotDisplay::DotDisplay(int dataPin, int clockPin, int latchPin,  int enableSubPanel1Pin, int enableSubPanel2Pin, int fontWidth, int fontHeight, byte fonteParam[][5]){

	pinMode(dataPin, OUTPUT);
	pinMode(clockPin, OUTPUT);
	pinMode(latchPin, OUTPUT);
	pinMode(enableSubPanel1Pin, OUTPUT);
	pinMode(enableSubPanel2Pin, OUTPUT);
	//disable FP2800A's
	digitalWrite(enableSubPanel1Pin, LOW);
	digitalWrite(enableSubPanel2Pin, LOW);

	_dataPin = dataPin;
	_clockPin = clockPin;
	_latchPin = latchPin;
	_enableSubPanel1Pin = enableSubPanel1Pin;
	_enableSubPanel2Pin = enableSubPanel2Pin;
	_fontWidth = fontWidth;
	_fontHeight = fontHeight;
	_fonteParam = fonteParam;

	//_maxNumRows = floor((DISPLAY_PIXEL_HEIGHT+1)/(_fontHeight));
	_maxNumRows = (int)((DISPLAY_PIXEL_HEIGHT+1)/(_fontHeight));
	//_maxRowLength = floor((DISPLAY_PIXEL_WIDTH * DISPLAY_SUBPANEL_QTY+1) / (_fontWidth+1));
	_maxRowLength = (int)((DISPLAY_PIXEL_WIDTH * DISPLAY_SUBPANEL_QTY+1) / (_fontWidth+1));
	_maxMessageLength = _maxRowLength * _maxNumRows;

}
/*
void DotDisplay::setSerial(HardwareSerial* hwPrint){
	printer = hwPrint; //operate on the address of print
	if(printer) {
		printer->begin(9600);
	}
}
*/

void DotDisplay::setDot(byte col, byte row, bool on){

	//accidentally reversed two data pins, so reversing back on the code here
	//on = !on;

	//2 pins - Data
	//5 pins - Column
	//4 pins - Rows

	//4 pins - Enable FP2800A (4 subpanels)
	byte subPanel = 1;
	//disable FP2800A's
	digitalWrite(_enableSubPanel1Pin, LOW);
	digitalWrite(_enableSubPanel2Pin, LOW);

	//enables next sunpanel
	if(col>=DISPLAY_PIXEL_WIDTH){
		//subPanel =  floor(col / DISPLAY_PIXEL_WIDTH)+1;
		subPanel =  (int)(col / DISPLAY_PIXEL_WIDTH)+1;
		col=col-DISPLAY_PIXEL_WIDTH;
	}

	/*
	if(printer) {
	printer->print("col: ");
	printer->print(col);
	printer->print(", ");
	printer->print("subPanel: ");
	printer->println(subPanel);
	}
	*/

	// IGNOREx4 + ROWx4 + IGNOREx1 + COLUMNx5 + DATAx2
	byte dataPins = on?1:2;
	byte colFirstThreeDigits = (col % 7)+1;
	//byte colLastTwoDigits = floor(col/7);
	byte colLastTwoDigits = (int)(col/7);
	byte colByte = colFirstThreeDigits | (colLastTwoDigits << 3);
	byte rowFirstThreeDigits = (row % 7)+1;
	byte rowLastDigit = row<7;
	byte rowByte = rowFirstThreeDigits | (rowLastDigit << 3);
	byte firstbyte = (dataPins) | (colByte << 2);
	byte secondbyte = rowByte;

	digitalWrite(_latchPin, LOW);
	shiftOut(_dataPin, _clockPin, LSBFIRST, firstbyte);
	shiftOut(_dataPin, _clockPin, LSBFIRST, secondbyte);
	digitalWrite(_latchPin, HIGH);
	//delay(1);

	//pulse the FP2800A's enable pins
	if(subPanel == 1){
		digitalWrite(_enableSubPanel1Pin, HIGH);
		delay(1);
		digitalWrite(_enableSubPanel1Pin, LOW);
	} else if (subPanel == 2) {
		digitalWrite(_enableSubPanel2Pin, HIGH);
		delay(1);
		digitalWrite(_enableSubPanel2Pin, LOW);
	}
}

//void DotDisplay::updateDisplay(char *textMessage){
void DotDisplay::updateDisplay(char textMessage[], char log[]){
	int currentColumn = 0;
	int currentRow = 0;

	strcpy(log,"");

	//goes through all characters
	for (int ch = 0; ch < (_maxMessageLength);ch++){
		//get a character from the message
		int alphabetIndex = textMessage[ch] - ' '; //Subtract '@' so we get a number

		//Serial.println(alphabetIndex);
		if ((alphabetIndex < 0) or (ch >=strlen(textMessage))) alphabetIndex=0;

		//push it to the next row if necessary
		if((currentColumn + _fontWidth) > (DISPLAY_PIXEL_WIDTH * DISPLAY_SUBPANEL_QTY)){
			currentColumn=0;
			currentRow=currentRow+_fontHeight;
		}

		//set all the bits in the next _fontWidth columns on the display
		for(byte col = currentColumn; col<(currentColumn+_fontWidth); col++){

			byte calculatedColumn = (col)%(_fontWidth+1);
			//for(byte row = 0; row < _fontHeight; row++)
			int characterRow = 0;
			for(byte row = currentRow; row < (currentRow + _fontHeight); row++){
				//bool isOn = bitRead(pgm_read_byte(&(_fonteParam[alphabetIndex][calculatedColumn])),6-characterRow);
				bool isOn = bitRead((byte)_fonteParam[alphabetIndex][calculatedColumn],6-row);//this index is needed as we are going from back to front

				setDot(col, row, isOn);
				/*
				if(printer) {
					printer->print(isOn);
				}
				*/
				char dot;
				if (isOn) dot = '1' else dot = '0';
				strcat(log,isOn);

				characterRow++;
			}
			/*
			if(printer) {
				printer->println("");
			}
			*/
			strcat(log,"");
		}
		/*
		if(printer) {
			printer->println("*******");
		}
		*/
		strcat(log,"*********");

		currentColumn = currentColumn+(_fontWidth+1);
	}
}
<|endoftext|>


<commit_before>// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com

// ============================================================================
// Copyright (c) 2017-2019, by Vitaly Grigoriev, <Vit.link420@gmail.com>.
// This file is part of ProtocolAnalyzer open source project under MIT License.
// ============================================================================

#ifndef PROTOCOL_ANALYZER_LOCKED_DEQUE_HPP
#define PROTOCOL_ANALYZER_LOCKED_DEQUE_HPP

#include <mutex>    // std::mutex, std::scoped_lock, std::lock_guard.
#include <deque>    // std::deque.
#include <utility>  // std::move, std::swap.

// In Common library MUST NOT use any another framework libraries because it is a core library.

namespace analyzer::framework::common::types
{
    /**
     * @class LockedDeque   LockedDeque.hpp   "include/framework/LockedDeque.hpp"
     * @brief This class defined concurrency wrapper over STL deque class to work in parallel threads.
     *
     * @tparam [in] Type - Typename of stored data in STL deque.
     *
     * @note This deque container if type-protected and provides a convenient RAII-style mechanism.
     *
     * @todo Set the global limit for adding new values to the deque.
     */
    template <typename Type>
    class LockedDeque
    {
    private:
        /**
         * @brief Mutex value for thread-safe class working.
         */
        std::mutex mutex = { };
        /**
         * @brief STL deque for stored data;
         */
        std::deque<Type> deque = { };

    public:
        /**
         * @brief Default constructor.
         *
         * @throw std::bad_alloc - In case when do not system memory to allocate the storage.
         */
        LockedDeque(void) noexcept(std::is_nothrow_default_constructible_v<std::deque<Type>>) = default;

        /**
         * @brief Default destructor.
         */
        ~LockedDeque(void) noexcept = default;

        /**
         * @brief Copy assignment constructor with LockedDeque<Type>.
         *
         * @tparam [in] other - The const reference of copied LockedDeque<Type>.
         *
         * @throw std::bad_alloc - In case when do not system memory to allocate the storage.
         */
        LockedDeque (const LockedDeque<Type>& other) noexcept(std::is_nothrow_copy_constructible_v<std::deque<Type>>)
        {
            try { std::scoped_lock lock { mutex, other.mutex }; }
            catch (const std::system_error& /*err*/) {
                return;
            }
            deque = other.deque;
        }

        /**
         * @brief Copy assignment constructor with STL std::deque<Type>.
         *
         * @tparam [in] other - The const reference of copied STL std::deque<Type>.
         *
         * @throw std::bad_alloc - In case when do not system memory to allocate the storage.
         */
        explicit LockedDeque (const std::deque<Type>& other) noexcept(std::is_nothrow_copy_constructible_v<std::deque<Type>>)
        {
            try { std::lock_guard<std::mutex> lock { mutex }; }
            catch (const std::system_error& /*err*/) {
                return;
            }
            deque = other;
        }

        /**
         * @brief Move assignment constructor with LockedDeque<Type>.
         *
         * @tparam [in] other - The rvalue reference of moved LockedDeque<Type>.
         */
        LockedDeque (LockedDeque<Type>&& other) noexcept
        {
            try { std::scoped_lock lock { mutex, other.mutex }; }
            catch (const std::system_error& /*err*/) {
                return;
            }
            deque = std::move(other.deque);
        }

        /**
         * @brief Move assignment constructor with STL std::deque<Type>.
         *
         * @tparam [in] other - The rvalue reference of moved STL std::deque<Type>.
         */
        explicit LockedDeque (std::deque<Type>&& other) noexcept
        {
            try { std::lock_guard<std::mutex> lock { mutex }; }
            catch (const std::system_error& /*err*/) {
                return;
            }
            deque = std::move(other);
        }

        /**
         * @brief Copy assignment operator.
         *
         * @tparam [in] other - The const reference of copied LockedDeque<Type> class.
         * @return Reference of the current LockedDeque<Type> class.
         *
         * @throw std::bad_alloc - In case when do not system memory to allocate the storage.
         */
        LockedDeque<Type>& operator= (const LockedDeque<Type>& other) noexcept(std::is_nothrow_copy_assignable_v<std::deque<Type>>)
        {
            if (this != &other)
            {
                try { std::scoped_lock lock { mutex, other.mutex }; }
                catch (const std::system_error& /*err*/) {
                    return *this;
                }
                deque = other.deque;
            }
            return *this;
        }

        /**
         * @brief Move assignment operator.
         *
         * @tparam [in] other - The rvalue reference of moved LockedDeque<Type> class.
         * @return Reference of the current LockedDeque<Type> class.
         */
        LockedDeque<Type>& operator= (LockedDeque<Type>&& other) noexcept
        {
            if (this != &other)
            {
                try { std::scoped_lock lock { mutex, other.mutex }; }
                catch (const std::system_error& /*err*/) {
                    return *this;
                }
                deque = std::move(other.deque);
            }
            return *this;
        }

        /**
         * @brief Method that returns the size of deque.
         *
         * @return Size of deque.
         */
        std::size_t Size(void) noexcept
        {
            try { std::lock_guard<std::mutex> lock { mutex }; }
            catch (const std::system_error& /*err*/) {
                return 0;
            }
            return deque.size();
        }

        /**
         * @brief Method that returns the internal state of deque.
         *
         * @return TRUE - if the container size is 0, otherwise - FALSE.
         */
        bool IsEmpty(void) noexcept
        {
            try { std::lock_guard<std::mutex> lock { mutex }; }
            catch (const std::system_error& /*err*/) {
                return false;
            }
            return deque.empty();
        }

        /**
         * @brief Method that push new value to front of deque.
         *
         * @tparam [in] value - New value for insert.
         * @return TRUE - if push is successful, otherwise - FALSE.
         */
        bool Push (const Type& value) noexcept
        {
            try {
                std::lock_guard<std::mutex> lock { mutex };
                deque.push_front(value);
            }
            catch (const std::exception& /*err*/) {
                return false;
            }
            return true;
        }

        /**
         * @brief Method that pop value from back of deque.
         *
         * @tparam [out] result - Returned value.
         * @return TRUE - if pop back element is successful, otherwise - FALSE.
         *
         * @note Use this method for pop the oldest value in the deque.
         */
        bool PopBack (Type& result) noexcept
        {
            try { std::lock_guard<std::mutex> lock { mutex }; }
            catch (const std::exception& /*err*/) {
                return false;
            }

            if (deque.empty() == true) {
                return false;
            }
            result = deque.back();
            deque.pop_back();
            return true;
        }

        /**
         * @brief Method that pop value from front of deque.
         *
         * @tparam [out] result - Returned value.
         * @return TRUE - if pop the front element is successful, otherwise - FALSE.
         */
        bool PopFront (Type& result) noexcept
        {
            try { std::lock_guard<std::mutex> lock { mutex }; }
            catch (const std::system_error& /*err*/) {
                return false;
            }

            if (deque.empty() == true) {
                return false;
            }
            result = deque.front();
            deque.pop_front();
            return true;
        }

        /**
         * @brief Method that moves all internal values to outside STL std::deque<Type>.
         *
         * @tparam [out] result - Returned value.
         * @return TRUE - if at least one element has been moved, otherwise - FALSE.
         */
        bool Move (std::deque<Type>& result) noexcept
        {
            try { std::lock_guard<std::mutex> lock { mutex }; }
            catch (const std::system_error& /*err*/) {
                return false;
            }

            if (deque.empty() == true) {
                return false;
            }
            result = std::move(deque);
            return true;
        }

        /**
         * @brief Method that swaps internal value with outside LockedDeque<Type> object.
         *
         * @tparam [in,out] other - Swapped value reference.
         * @return TRUE - if swap is successful, otherwise - FALSE.
         */
        bool Swap (LockedDeque<Type>& other) noexcept
        {
            if (this != &other)
            {
                try { std::scoped_lock lock { mutex, other.mutex }; }
                catch (const std::system_error& /*err*/) {
                    return false;
                }
                std::swap(deque, other.deque);
            }
            return true;
        }

        /**
         * @brief Method that swaps internal value with outside STL std::deque<Type>.
         *
         * @tparam [in,out] other - Swapped value reference.
         * @return TRUE - if swap is successful, otherwise - FALSE.
         */
        bool Swap (std::deque<Type>& other) noexcept
        {
            try { std::lock_guard<std::mutex> lock { mutex }; }
            catch (const std::system_error& /*err*/) {
                return false;
            }
            std::swap(deque, other);
            return true;
        }

        /**
         * @brief Method that clears the deque.
         *
         * @return TRUE - if clear is successful, otherwise - FALSE.
         */
        bool Clear(void) noexcept
        {
            try { std::lock_guard<std::mutex> lock { mutex }; }
            catch (const std::system_error& /*err*/) {
                return false;
            }
            deque.clear();
            return true;
        }
    };

}  // namespace types.

#endif  // PROTOCOL_ANALYZER_LOCKED_DEQUE_HPP
<commit_msg>[FRAMEWORK/DATA] Fix logical error in LockedDeque class.<commit_after>// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com

// ============================================================================
// Copyright (c) 2017-2019, by Vitaly Grigoriev, <Vit.link420@gmail.com>.
// This file is part of ProtocolAnalyzer open source project under MIT License.
// ============================================================================

#ifndef PROTOCOL_ANALYZER_LOCKED_DEQUE_HPP
#define PROTOCOL_ANALYZER_LOCKED_DEQUE_HPP

#include <mutex>    // std::mutex, std::scoped_lock, std::lock_guard.
#include <deque>    // std::deque.
#include <utility>  // std::move, std::swap.

// In Common library MUST NOT use any another framework libraries because it is a core library.

namespace analyzer::framework::common::types
{
    /**
     * @class LockedDeque   LockedDeque.hpp   "include/framework/LockedDeque.hpp"
     * @brief This class defined concurrency wrapper over STL deque class to work in parallel threads.
     *
     * @tparam [in] Type - Typename of stored data in STL deque.
     *
     * @note This deque container if type-protected and provides a convenient RAII-style mechanism.
     *
     * @todo Set the global limit for adding new values to the deque.
     */
    template <typename Type>
    class LockedDeque
    {
    private:
        /**
         * @brief Mutex value for thread-safe class working.
         */
        std::mutex mutex = { };
        /**
         * @brief STL deque for stored data;
         */
        std::deque<Type> deque = { };

    public:
        /**
         * @brief Default constructor.
         *
         * @throw std::bad_alloc - If there is not enough system memory for allocate the storage.
         */
        LockedDeque(void) noexcept(std::is_nothrow_default_constructible_v<std::deque<Type>>) = default;

        /**
         * @brief Default destructor.
         */
        ~LockedDeque(void) noexcept = default;

        /**
         * @brief Copy assignment constructor with LockedDeque.
         *
         * @tparam [in] other - Constant lvalue reference of copied LockedDeque.
         *
         * @throw std::bad_alloc - If there is not enough system memory for allocate the storage.
         */
        LockedDeque (const LockedDeque& other) noexcept(std::is_nothrow_copy_constructible_v<std::deque<Type>>)
        {
            try
            {
                std::scoped_lock lock { mutex, other.mutex };
                deque = other.deque;
            }
            catch (const std::system_error& /*err*/) { }
        }

        /**
         * @brief Copy assignment constructor with STL std::deque.
         *
         * @tparam [in] other - Constant lvalue reference of copied STL std::deque.
         *
         * @throw std::bad_alloc - If there is not enough system memory for allocate the storage.
         */
        explicit LockedDeque (const std::deque<Type>& other) noexcept(std::is_nothrow_copy_constructible_v<std::deque<Type>>)
        {
            try
            {
                std::lock_guard<std::mutex> lock { mutex };
                deque = other;
            }
            catch (const std::system_error& /*err*/) { }
        }

        /**
         * @brief Move assignment constructor with LockedDeque.
         *
         * @tparam [in] other - Rvalue reference of moved LockedDeque.
         */
        LockedDeque (LockedDeque&& other) noexcept
        {
            try
            {
                std::scoped_lock lock { mutex, other.mutex };
                deque = std::move(other.deque);
            }
            catch (const std::system_error& /*err*/) { }
        }

        /**
         * @brief Move assignment constructor with STL std::deque.
         *
         * @tparam [in] other - Rvalue reference of moved STL std::deque.
         */
        explicit LockedDeque (std::deque<Type>&& other) noexcept
        {
            try
            {
                std::lock_guard<std::mutex> lock { mutex };
                deque = std::move(other);
            }
            catch (const std::system_error& /*err*/) { }
        }

        /**
         * @brief Copy assignment operator.
         *
         * @tparam [in] other - Constant lvalue reference of copied LockedDeque class.
         * @return Lvalue reference of current LockedDeque class.
         *
         * @throw std::bad_alloc - If there is not enough system memory for allocate the storage.
         */
        LockedDeque& operator= (const LockedDeque& other) noexcept(std::is_nothrow_copy_assignable_v<std::deque<Type>>)
        {
            if (this != &other)
            {
                try
                {
                    std::scoped_lock lock { mutex, other.mutex };
                    deque = other.deque;
                }
                catch (const std::system_error& /*err*/) { }
            }
            return *this;
        }

        /**
         * @brief Move assignment operator.
         *
         * @tparam [in] other - Rvalue reference of moved LockedDeque class.
         * @return Lvalue reference of current LockedDeque class.
         */
        LockedDeque& operator= (LockedDeque&& other) noexcept
        {
            if (this != &other)
            {
                try
                {
                    std::scoped_lock lock { mutex, other.mutex };
                    deque = std::move(other.deque);
                }
                catch (const std::system_error& /*err*/) { }
            }
            return *this;
        }

        /**
         * @brief Method that returns the size of deque.
         *
         * @return Size of deque.
         */
        std::size_t Size(void) noexcept
        {
            try
            {
                std::lock_guard<std::mutex> lock { mutex };
                return deque.size();
            }
            catch (const std::system_error& /*err*/) {
                return 0;
            }
        }

        /**
         * @brief Method that returns the internal state of deque.
         *
         * @return TRUE - if container is empty, otherwise - FALSE.
         */
        bool IsEmpty(void) noexcept
        {
            try
            {
                std::lock_guard<std::mutex> lock { mutex };
                return deque.empty();
            }
            catch (const std::system_error& /*err*/) {
                return false;
            }
        }

        /**
         * @brief Method that push new value to front of deque.
         *
         * @tparam [in] value - New value for insert.
         * @return TRUE - if pushing is successful, otherwise - FALSE.
         */
        bool Push (const Type& value) noexcept
        {
            try
            {
                std::lock_guard<std::mutex> lock { mutex };
                deque.push_front(value);
            }
            catch (const std::exception& /*err*/) {
                return false;
            }
            return true;
        }

        /**
         * @brief Method that pops value from the back of deque.
         *
         * @tparam [out] result - Returned value.
         * @return TRUE - if popping element from back is successful, otherwise - FALSE.
         *
         * @note Use this method for pop the oldest value in the deque.
         */
        bool PopBack (Type& result) noexcept
        {
            try
            {
                std::lock_guard<std::mutex> lock { mutex };
                if (deque.empty() == true) {
                    return false;
                }
                result = deque.back();
                deque.pop_back();
            }
            catch (const std::exception& /*err*/) {
                return false;
            }
            return true;
        }

        /**
         * @brief Method that pops value from the front of deque.
         *
         * @tparam [out] result - Returned value.
         * @return TRUE - if popping element from front is successful, otherwise - FALSE.
         */
        bool PopFront (Type& result) noexcept
        {
            try
            {
                std::lock_guard<std::mutex> lock { mutex };
                if (deque.empty() == true) {
                    return false;
                }
                result = deque.front();
                deque.pop_front();
            }
            catch (const std::system_error& /*err*/) {
                return false;
            }
            return true;
        }

        /**
         * @brief Method that moves all internal values to outside STL std::deque.
         *
         * @tparam [out] result - Returned value.
         * @return TRUE - if at least one element has been moved, otherwise - FALSE.
         */
        bool Move (std::deque<Type>& result) noexcept
        {
            try
            {
                std::lock_guard<std::mutex> lock { mutex };
                if (deque.empty() == true) {
                    return false;
                }
                result = std::move(deque);
            }
            catch (const std::system_error& /*err*/) {
                return false;
            }
            return true;
        }

        /**
         * @brief Method that swaps internal value with outside LockedDeque object.
         *
         * @tparam [in,out] other - Lvalue reference of swapped value.
         * @return TRUE - if swapping is successful, otherwise - FALSE.
         */
        bool Swap (LockedDeque& other) noexcept
        {
            if (this != &other)
            {
                try
                {
                    std::scoped_lock lock { mutex, other.mutex };
                    std::swap(deque, other.deque);
                }
                catch (const std::system_error& /*err*/) {
                    return false;
                }
            }
            return true;
        }

        /**
         * @brief Method that swaps internal value with outside STL std::deque.
         *
         * @tparam [in,out] other - Lvalue reference of swapped value.
         * @return TRUE - if swapping is successful, otherwise - FALSE.
         */
        bool Swap (std::deque<Type>& other) noexcept
        {
            try
            {
                std::lock_guard<std::mutex> lock { mutex };
                std::swap(deque, other);
            }
            catch (const std::system_error& /*err*/) {
                return false;
            }
            return true;
        }

        /**
         * @brief Method that clears the deque.
         *
         * @return TRUE - if clearing is successful, otherwise - FALSE.
         */
        bool Clear(void) noexcept
        {
            try
            {
                std::lock_guard<std::mutex> lock { mutex };
                deque.clear();
            }
            catch (const std::system_error& /*err*/) {
                return false;
            }
            return true;
        }
    };

}  // namespace types.

#endif  // PROTOCOL_ANALYZER_LOCKED_DEQUE_HPP
<|endoftext|>


<commit_before>//-----------------------------------------------------------------------------
// Jikken - 3D Abstract High Performance Graphics API
// Copyright(c) 2017 Jeff Hutchinson
// Copyright(c) 2017 Tim Barnes
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//-----------------------------------------------------------------------------

#ifndef _JIKKEN_GRAPHICSDEVICE_HPP_
#define _JIKKEN_GRAPHICSDEVICE_HPP_

#include <vector>
#include <string>
#include "jikken/enums.hpp"
#include "jikken/commands.hpp"
#include "jikken/commandQueue.hpp"

namespace Jikken
{
	struct ShaderDetails
	{
		std::string file;
		ShaderStage stage;
	};

	class GraphicsDevice
	{
	public:
		virtual ~GraphicsDevice() {}

		virtual ShaderHandle createShader(const std::vector<ShaderDetails> &shaders) = 0;

		virtual BufferHandle createBuffer(BufferType type, BufferUsageHint hint, size_t dataSize, float *data) = 0;

		virtual void deleteBuffer(BufferHandle handle) = 0;

		virtual void deleteShader(ShaderHandle handle) = 0;
	};
}

#endif<commit_msg>input layout and VAO<commit_after>//-----------------------------------------------------------------------------
// Jikken - 3D Abstract High Performance Graphics API
// Copyright(c) 2017 Jeff Hutchinson
// Copyright(c) 2017 Tim Barnes
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//-----------------------------------------------------------------------------

#ifndef _JIKKEN_GRAPHICSDEVICE_HPP_
#define _JIKKEN_GRAPHICSDEVICE_HPP_

#include <vector>
#include <string>
#include "jikken/enums.hpp"
#include "jikken/commands.hpp"
#include "jikken/commandQueue.hpp"

namespace Jikken
{
	enum VertexAttributeName : int32_t
	{
		ePOSITION = 0
	};

	enum VertexAttributeType : int32_t
	{
		eFLOAT = 0,
		eUNSIGNED_INTEGER = 1,
		eSIGNED_INTEGER = 2s
	};

	struct VertexInputLayout
	{
		VertexAttributeName attribute;
		int32_t componentSize;
		VertexAttributeType type;
		uint32_t stride;
		size_t offset;
	};

	struct ShaderDetails
	{
		std::string file;
		ShaderStage stage;
	};

	class GraphicsDevice
	{
	public:
		virtual ~GraphicsDevice() {}

		virtual ShaderHandle createShader(const std::vector<ShaderDetails> &shaders) = 0;

		virtual BufferHandle createBuffer(BufferType type, BufferUsageHint hint, size_t dataSize, float *data) = 0;

		virtual LayoutHandle createVertexInputLayout(const std::vector<VertexInputLayout> &attributes) = 0;

		virtual VertexArrayHandle createVertexArrayObject(LayoutHandle layout, BufferHandle vertexBuffer, BufferHandle indexBuffer = 0) = 0;

		virtual void deleteVertexInputLayout(LayoutHandle handle) = 0;

		virtual void deleteVertexArrayObject(VertexArrayHandle handle) = 0;

		virtual void deleteBuffer(BufferHandle handle) = 0;

		virtual void deleteShader(ShaderHandle handle) = 0;
	};
}

#endif
<|endoftext|>


<commit_before><commit_msg>WaE: implicit conversion (IntegralCast) from bool to 'unsigned long'<commit_after><|endoftext|>


<commit_before>/*

Copyright (c) 2007, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_PROXY_BASE_HPP_INCLUDED
#define TORRENT_PROXY_BASE_HPP_INCLUDED

#include "libtorrent/io.hpp"
#include "libtorrent/socket.hpp"
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/function.hpp>
#include <asio/read.hpp>
#include <asio/write.hpp>

namespace libtorrent {

class proxy_base : boost::noncopyable
{
public:

	typedef stream_socket::lowest_layer_type lowest_layer_type;
	typedef stream_socket::endpoint_type endpoint_type;
	typedef stream_socket::protocol_type protocol_type;

	explicit proxy_base(asio::io_service& io_service)
		: m_sock(io_service)
		, m_resolver(io_service)
	{}

	void set_proxy(std::string hostname, int port)
	{
		m_hostname = hostname;
		m_port = port;
	}

	template <class Mutable_Buffers, class Handler>
	void async_read_some(Mutable_Buffers const& buffers, Handler const& handler)
	{
		m_sock.async_read_some(buffers, handler);
	}

	template <class Mutable_Buffers>
	std::size_t read_some(Mutable_Buffers const& buffers, asio::error_code& ec)
	{
		return m_sock.read_some(buffers, ec);
	}

	template <class Mutable_Buffers>
	std::size_t read_some(Mutable_Buffers const& buffers)
	{
		return m_sock.read_some(buffers);
	}

	template <class IO_Control_Command>
	void io_control(IO_Control_Command& ioc)
	{
		m_sock.io_control(ioc);
	}

	template <class IO_Control_Command>
	void io_control(IO_Control_Command& ioc, asio::error_code& ec)
	{
		m_sock.io_control(ioc, ec);
	}

	template <class Const_Buffers, class Handler>
	void async_write_some(Const_Buffers const& buffers, Handler const& handler)
	{
		m_sock.async_write_some(buffers, handler);
	}

	void bind(endpoint_type const& endpoint)
	{
		m_sock.bind(endpoint);
	}

	template <class Error_Handler>
	void bind(endpoint_type const& endpoint, Error_Handler const& error_handler)
	{
		m_sock.bind(endpoint, error_handler);
	}

	void open(protocol_type const& p)
	{
		m_sock.open(p);
	}

	template <class Error_Handler>
	void open(protocol_type const& p, Error_Handler const& error_handler)
	{
		m_sock.open(p, error_handler);
	}

	void close()
	{
		m_remote_endpoint = endpoint_type();
		m_sock.close();
	}

	template <class Error_Handler>
	void close(Error_Handler const& error_handler)
	{
		m_sock.close(error_handler);
	}

	endpoint_type remote_endpoint()
	{
		return m_remote_endpoint;
	}

	template <class Error_Handler>
	endpoint_type remote_endpoint(Error_Handler const& error_handler)
	{
		return m_remote_endpoint;
	}

	endpoint_type local_endpoint()
	{
		return m_sock.local_endpoint();
	}

	template <class Error_Handler>
	endpoint_type local_endpoint(Error_Handler const& error_handler)
	{
		return m_sock.local_endpoint(error_handler);
	}

	asio::io_service& io_service()
	{
		return m_sock.io_service();
	}

	lowest_layer_type& lowest_layer()
	{
		return m_sock.lowest_layer();
	}

protected:

	stream_socket m_sock;
	std::string m_hostname;
	int m_port;

	endpoint_type m_remote_endpoint;

	tcp::resolver m_resolver;
};

}

#endif

<commit_msg>cleaned up unnecessary template functions<commit_after>/*

Copyright (c) 2007, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_PROXY_BASE_HPP_INCLUDED
#define TORRENT_PROXY_BASE_HPP_INCLUDED

#include "libtorrent/io.hpp"
#include "libtorrent/socket.hpp"
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/function.hpp>
#include <asio/read.hpp>
#include <asio/write.hpp>

namespace libtorrent {

class proxy_base : boost::noncopyable
{
public:

	typedef stream_socket::lowest_layer_type lowest_layer_type;
	typedef stream_socket::endpoint_type endpoint_type;
	typedef stream_socket::protocol_type protocol_type;

	explicit proxy_base(asio::io_service& io_service)
		: m_sock(io_service)
		, m_resolver(io_service)
	{}

	void set_proxy(std::string hostname, int port)
	{
		m_hostname = hostname;
		m_port = port;
	}

	template <class Mutable_Buffers, class Handler>
	void async_read_some(Mutable_Buffers const& buffers, Handler const& handler)
	{
		m_sock.async_read_some(buffers, handler);
	}

	template <class Mutable_Buffers>
	std::size_t read_some(Mutable_Buffers const& buffers, asio::error_code& ec)
	{
		return m_sock.read_some(buffers, ec);
	}

	template <class Mutable_Buffers>
	std::size_t read_some(Mutable_Buffers const& buffers)
	{
		return m_sock.read_some(buffers);
	}

	template <class IO_Control_Command>
	void io_control(IO_Control_Command& ioc)
	{
		m_sock.io_control(ioc);
	}

	template <class IO_Control_Command>
	void io_control(IO_Control_Command& ioc, asio::error_code& ec)
	{
		m_sock.io_control(ioc, ec);
	}

	template <class Const_Buffers, class Handler>
	void async_write_some(Const_Buffers const& buffers, Handler const& handler)
	{
		m_sock.async_write_some(buffers, handler);
	}

	void bind(endpoint_type const& endpoint)
	{
		m_sock.bind(endpoint);
	}

	void bind(endpoint_type const& endpoint, asio::error_code& ec)
	{
		m_sock.bind(endpoint, ec);
	}

	void open(protocol_type const& p)
	{
		m_sock.open(p);
	}

	void open(protocol_type const& p, asio::error_code& ec)
	{
		m_sock.open(p, ec);
	}

	void close()
	{
		m_remote_endpoint = endpoint_type();
		m_sock.close();
	}

	void close(asio::error_code& ec)
	{
		m_sock.close(ec);
	}

	endpoint_type remote_endpoint()
	{
		return m_remote_endpoint;
	}

	endpoint_type remote_endpoint(asio::error_code& ec)
	{
		return m_remote_endpoint;
	}

	endpoint_type local_endpoint()
	{
		return m_sock.local_endpoint();
	}

	endpoint_type local_endpoint(asio::error_code& ec)
	{
		return m_sock.local_endpoint(ec);
	}

	asio::io_service& io_service()
	{
		return m_sock.io_service();
	}

	lowest_layer_type& lowest_layer()
	{
		return m_sock.lowest_layer();
	}

protected:

	stream_socket m_sock;
	std::string m_hostname;
	int m_port;

	endpoint_type m_remote_endpoint;

	tcp::resolver m_resolver;
};

}

#endif

<|endoftext|>