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

#ifndef ETL_CONVOLUTION_HPP
#define ETL_CONVOLUTION_HPP

#include <algorithm>

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

namespace etl {

template<std::size_t T, typename I, typename K, typename C, cpp::disable_if_all_u<etl_traits<I>::is_fast, etl_traits<K>::is_fast, etl_traits<C>::is_fast> = cpp::detail::dummy>
void check_conv_1d_sizes(const I& input, const K& kernel, const C& conv){
    if(T == 1){
        cpp_assert(dim<0>(conv) == dim<0>(input) + dim<0>(kernel) - 1, "Invalid sizes for 'full' convolution");
    } else if(T == 2){
        cpp_assert(dim<0>(conv) == dim<0>(input), "Invalid sizes for 'same' convolution");
    } else if(T == 3){
        cpp_assert(dim<0>(conv) == dim<0>(input) - dim<0>(kernel) + 1, "Invalid sizes for 'valid' convolution");
    }
    cpp_unused(input);
    cpp_unused(kernel);
    cpp_unused(conv);
}

template<std::size_t T, typename I, typename K, typename C, cpp::enable_if_all_u<etl_traits<I>::is_fast, etl_traits<K>::is_fast, etl_traits<C>::is_fast> = cpp::detail::dummy>
void check_conv_1d_sizes(const I&, const K&, const C&){
    static_assert(
        T != 1 || etl_traits<C>::template dim<0>() == etl_traits<I>::template dim<0>() + etl_traits<K>::template dim<0>() - 1,
        "Invalid sizes for 'full'convolution");
    static_assert(
        T != 2 || etl_traits<C>::template dim<0>() == etl_traits<I>::template dim<0>(),
        "Invalid sizes for 'same'convolution");
    static_assert(
        T != 3 || etl_traits<C>::template dim<0>() == etl_traits<I>::template dim<0>() - etl_traits<K>::template dim<0>() + 1,
        "Invalid sizes for 'valid'convolution");
}

template<std::size_t T, typename I, typename K, typename C, cpp::disable_if_all_u<etl_traits<I>::is_fast, etl_traits<K>::is_fast, etl_traits<C>::is_fast> = cpp::detail::dummy>
void check_conv_2d_sizes(const I& input, const K& kernel, const C& conv){
    if(T == 1){
        cpp_assert(
                dim<0>(conv) == dim<0>(input) + dim<0>(kernel) - 1
            &&  dim<1>(conv) == dim<1>(input) + dim<1>(kernel) - 1,
            "Invalid sizes for 'valid' convolution");
    } else if(T == 2){
        cpp_assert(dim<0>(conv) == dim<0>(input) && dim<1>(conv) == dim<1>(input), "Invalid sizes for 'same' convolution");
    } else if(T == 3){
        cpp_assert(
                dim<0>(conv) == dim<0>(input) - dim<0>(kernel) + 1
            &&  dim<1>(conv) == dim<1>(input) - dim<1>(kernel) + 1,
            "Invalid sizes for 'valid' convolution");
    }
    cpp_unused(input);
    cpp_unused(kernel);
    cpp_unused(conv);
}

template<std::size_t T, typename I, typename K, typename C, cpp::enable_if_all_u<etl_traits<I>::is_fast, etl_traits<K>::is_fast, etl_traits<C>::is_fast> = cpp::detail::dummy>
void check_conv_2d_sizes(const I&, const K&, const C&){
    static_assert(
        T != 1 || (
                etl_traits<C>::template dim<0>() == etl_traits<I>::template dim<0>() + etl_traits<K>::template dim<0>() - 1
            &&  etl_traits<C>::template dim<1>() == etl_traits<I>::template dim<1>() + etl_traits<K>::template dim<1>() - 1),
        "Invalid sizes for 'full'convolution");
    static_assert(
        T != 2 || (
                etl_traits<C>::template dim<0>() == etl_traits<I>::template dim<0>()
            &&  etl_traits<C>::template dim<1>() == etl_traits<I>::template dim<1>()),
        "Invalid sizes for 'same'convolution");
    static_assert(
        T != 3 || (
                etl_traits<C>::template dim<0>() == etl_traits<I>::template dim<0>() - etl_traits<K>::template dim<0>() + 1
            &&  etl_traits<C>::template dim<1>() == etl_traits<I>::template dim<1>() - etl_traits<K>::template dim<1>() + 1),
        "Invalid sizes for 'valid'convolution");
}

template<typename I, typename K, typename C>
static C& convolve_1d_full(const I& input, const K& kernel, C&& conv){
    static_assert(is_etl_expr<I>::value && is_etl_expr<K>::value && is_etl_expr<C>::value, "Convolution only supported for ETL expressions");
    check_conv_1d_sizes<1>(input, kernel, conv);

    for(std::size_t i = 0; i < size(conv); ++i) {
        const auto lo = i >= size(kernel) - 1 ? i - (size(kernel) - 1) : 0;
        const auto hi = i < size(input) - 1 ? i : size(input) - 1;

        double temp = 0.0;

        for(std::size_t j = lo; j <= hi; ++j) {
            temp += input[j] * kernel[i - j];
        }

        conv[i] = temp;
    }

    return conv;
}

template<typename I, typename K, typename C>
static C& convolve_1d_same(const I& input, const K& kernel, C&& conv){
    static_assert(is_etl_expr<I>::value && is_etl_expr<K>::value && is_etl_expr<C>::value, "Convolution only supported for ETL expressions");
    check_conv_1d_sizes<2>(input, kernel, conv);

    for(std::size_t j = 0 ; j < size(conv) ; ++j){
        int l_lo = std::max<int>(0, j - (size(kernel) - 1) / 2);
        int l_hi = std::min<int>(size(input)- 1, j + size(kernel) / 2);

        double temp = 0.0;

        for(std::size_t l = l_lo ; l <= static_cast<std::size_t>(l_hi); ++l){
            temp += input(l) * kernel(j - l + size(kernel) / 2);
        }

        conv(0 + j) = temp;
    }

    return conv;
}

template<typename I, typename K, typename C>
static C& convolve_1d_valid(const I& input, const K& kernel, C&& conv){
    static_assert(is_etl_expr<I>::value && is_etl_expr<K>::value && is_etl_expr<C>::value, "Convolution only supported for ETL expressions");
    check_conv_1d_sizes<3>(input, kernel, conv);

    for(std::size_t j = 0 ; j < size(conv) ; ++j){
        double temp = 0.0;

        for(std::size_t l = j ; l <= j + size(kernel) - 1; ++l){
            temp += input[l] * kernel[j + size(kernel) - 1 - l];
        }

        conv[j] = temp;
    }

    return conv;
}

template<typename I, typename K, typename C>
static C& convolve_2d_full(const I& input, const K& kernel, C&& conv){
    static_assert(is_etl_expr<I>::value && is_etl_expr<K>::value && is_etl_expr<C>::value, "Convolution only supported for ETL expressions");
    check_conv_2d_sizes<1>(input, kernel, conv);

    for(std::size_t i = 0 ; i < rows(conv) ; ++i){
        auto k_lo = std::max<int>(0, i - rows(kernel) + 1);
        auto k_hi = std::min(rows(input) - 1, i);

        for(std::size_t j = 0 ; j < columns(conv) ; ++j){
            auto l_lo = std::max<int>(0, j - columns(kernel) + 1);
            auto l_hi = std::min(columns(input) - 1 ,j);

            double temp = 0.0;

            for(std::size_t k = k_lo ; k <= k_hi ; ++k){
                for(std::size_t l = l_lo ; l <= l_hi ; ++l){
                    temp += input(k,l) * kernel(i - k, j - l);
                }
            }

            conv(i, j) = temp;
        }
    }

    return conv;
}

template<typename I, typename K, typename C>
static C& convolve_2d_same(const I& input, const K& kernel, C&& conv){
    static_assert(is_etl_expr<I>::value && is_etl_expr<K>::value && is_etl_expr<C>::value, "Convolution only supported for ETL expressions");
    check_conv_2d_sizes<2>(input, kernel, conv);

    for(std::size_t i = 0 ; i < rows(conv); ++i){
        auto k_lo = std::max<int>(0, i - (rows(kernel)-1)/2);
        auto k_hi = std::min<int>(rows(input) - 1, i + rows(kernel)/2);

        for(std::size_t j = 0 ; j < columns(conv); ++j){
            auto l_lo = std::max<int>(0, j - (columns(kernel)-1)/2);
            auto l_hi = std::min<int>(columns(input) - 1, j + columns(kernel)/2);

            double temp = 0.0;

            for(int k = k_lo ; k <= k_hi ; ++k){
                for(std::size_t l = l_lo ; l <= static_cast<std::size_t>(l_hi); ++l){
                    temp += input(k, l) * kernel(i-k+rows(kernel)/2, j-l+columns(kernel)/2);
                }
            }

            conv(i, j) = temp;
        }
    }

    return conv;
}

template<typename I, typename K, typename C>
static C& convolve_2d_valid(const I& input, const K& kernel, C&& conv){
    static_assert(is_etl_expr<I>::value && is_etl_expr<K>::value && is_etl_expr<C>::value, "Convolution only supported for ETL expressions");
    check_conv_2d_sizes<3>(input, kernel, conv);

    for(std::size_t i = 0 ; i < rows(conv) ; ++i){
        for(std::size_t j = 0 ; j < columns(conv) ; ++j){
            double temp = 0.0;

            for(std::size_t k = i ; k <= i + rows(kernel)-1; ++k){
                for(std::size_t l = j ; l <= j + columns(kernel)-1 ; ++l){
                    temp += input(k,l) * kernel((i+rows(kernel)-1-k), (j+columns(kernel)-1-l));
                }
            }

            conv(i,j) = temp;
        }
    }

    return conv;
}

} //end of namespace etl

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

#ifndef ETL_CONVOLUTION_HPP
#define ETL_CONVOLUTION_HPP

#include <algorithm>

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

namespace etl {

template<std::size_t T, typename I, typename K, typename C, cpp::disable_if_all_u<etl_traits<I>::is_fast, etl_traits<K>::is_fast, etl_traits<C>::is_fast> = cpp::detail::dummy>
void check_conv_1d_sizes(const I& input, const K& kernel, const C& conv){
    static_assert(etl_traits<I>::dimensions() == 1 && etl_traits<K>::dimensions() == 1 && etl_traits<C>::dimensions() == 1, "Invalid dimensions for 1D convolution");

    if(T == 1){
        cpp_assert(dim<0>(conv) == dim<0>(input) + dim<0>(kernel) - 1, "Invalid sizes for 'full' convolution");
    } else if(T == 2){
        cpp_assert(dim<0>(conv) == dim<0>(input), "Invalid sizes for 'same' convolution");
    } else if(T == 3){
        cpp_assert(dim<0>(conv) == dim<0>(input) - dim<0>(kernel) + 1, "Invalid sizes for 'valid' convolution");
    }

    cpp_unused(input);
    cpp_unused(kernel);
    cpp_unused(conv);
}

template<std::size_t T, typename I, typename K, typename C, cpp::enable_if_all_u<etl_traits<I>::is_fast, etl_traits<K>::is_fast, etl_traits<C>::is_fast> = cpp::detail::dummy>
void check_conv_1d_sizes(const I&, const K&, const C&){
    static_assert(etl_traits<I>::dimensions() == 1 && etl_traits<K>::dimensions() == 1 && etl_traits<C>::dimensions() == 1, "Invalid dimensions for 1D convolution");

    static_assert(
        T != 1 || etl_traits<C>::template dim<0>() == etl_traits<I>::template dim<0>() + etl_traits<K>::template dim<0>() - 1,
        "Invalid sizes for 'full'convolution");
    static_assert(
        T != 2 || etl_traits<C>::template dim<0>() == etl_traits<I>::template dim<0>(),
        "Invalid sizes for 'same'convolution");
    static_assert(
        T != 3 || etl_traits<C>::template dim<0>() == etl_traits<I>::template dim<0>() - etl_traits<K>::template dim<0>() + 1,
        "Invalid sizes for 'valid'convolution");
}

template<std::size_t T, typename I, typename K, typename C, cpp::disable_if_all_u<etl_traits<I>::is_fast, etl_traits<K>::is_fast, etl_traits<C>::is_fast> = cpp::detail::dummy>
void check_conv_2d_sizes(const I& input, const K& kernel, const C& conv){
    static_assert(etl_traits<I>::dimensions() == 2 && etl_traits<K>::dimensions() == 2 && etl_traits<C>::dimensions() == 2, "Invalid dimensions for 2D convolution");

    if(T == 1){
        cpp_assert(
                dim<0>(conv) == dim<0>(input) + dim<0>(kernel) - 1
            &&  dim<1>(conv) == dim<1>(input) + dim<1>(kernel) - 1,
            "Invalid sizes for 'valid' convolution");
    } else if(T == 2){
        cpp_assert(dim<0>(conv) == dim<0>(input) && dim<1>(conv) == dim<1>(input), "Invalid sizes for 'same' convolution");
    } else if(T == 3){
        cpp_assert(
                dim<0>(conv) == dim<0>(input) - dim<0>(kernel) + 1
            &&  dim<1>(conv) == dim<1>(input) - dim<1>(kernel) + 1,
            "Invalid sizes for 'valid' convolution");
    }

    cpp_unused(input);
    cpp_unused(kernel);
    cpp_unused(conv);
}

template<std::size_t T, typename I, typename K, typename C, cpp::enable_if_all_u<etl_traits<I>::is_fast, etl_traits<K>::is_fast, etl_traits<C>::is_fast> = cpp::detail::dummy>
void check_conv_2d_sizes(const I&, const K&, const C&){
    static_assert(etl_traits<I>::dimensions() == 2 && etl_traits<K>::dimensions() == 2 && etl_traits<C>::dimensions() == 2, "Invalid dimensions for 2D convolution");

    static_assert(
        T != 1 || (
                etl_traits<C>::template dim<0>() == etl_traits<I>::template dim<0>() + etl_traits<K>::template dim<0>() - 1
            &&  etl_traits<C>::template dim<1>() == etl_traits<I>::template dim<1>() + etl_traits<K>::template dim<1>() - 1),
        "Invalid sizes for 'full'convolution");
    static_assert(
        T != 2 || (
                etl_traits<C>::template dim<0>() == etl_traits<I>::template dim<0>()
            &&  etl_traits<C>::template dim<1>() == etl_traits<I>::template dim<1>()),
        "Invalid sizes for 'same'convolution");
    static_assert(
        T != 3 || (
                etl_traits<C>::template dim<0>() == etl_traits<I>::template dim<0>() - etl_traits<K>::template dim<0>() + 1
            &&  etl_traits<C>::template dim<1>() == etl_traits<I>::template dim<1>() - etl_traits<K>::template dim<1>() + 1),
        "Invalid sizes for 'valid'convolution");
}

template<typename I, typename K, typename C>
static C& convolve_1d_full(const I& input, const K& kernel, C&& conv){
    static_assert(is_etl_expr<I>::value && is_etl_expr<K>::value && is_etl_expr<C>::value, "Convolution only supported for ETL expressions");
    check_conv_1d_sizes<1>(input, kernel, conv);

    for(std::size_t i = 0; i < size(conv); ++i) {
        const auto lo = i >= size(kernel) - 1 ? i - (size(kernel) - 1) : 0;
        const auto hi = i < size(input) - 1 ? i : size(input) - 1;

        double temp = 0.0;

        for(std::size_t j = lo; j <= hi; ++j) {
            temp += input[j] * kernel[i - j];
        }

        conv[i] = temp;
    }

    return conv;
}

template<typename I, typename K, typename C>
static C& convolve_1d_same(const I& input, const K& kernel, C&& conv){
    static_assert(is_etl_expr<I>::value && is_etl_expr<K>::value && is_etl_expr<C>::value, "Convolution only supported for ETL expressions");
    check_conv_1d_sizes<2>(input, kernel, conv);

    for(std::size_t j = 0 ; j < size(conv) ; ++j){
        int l_lo = std::max<int>(0, j - (size(kernel) - 1) / 2);
        int l_hi = std::min<int>(size(input)- 1, j + size(kernel) / 2);

        double temp = 0.0;

        for(std::size_t l = l_lo ; l <= static_cast<std::size_t>(l_hi); ++l){
            temp += input(l) * kernel(j - l + size(kernel) / 2);
        }

        conv(0 + j) = temp;
    }

    return conv;
}

template<typename I, typename K, typename C>
static C& convolve_1d_valid(const I& input, const K& kernel, C&& conv){
    static_assert(is_etl_expr<I>::value && is_etl_expr<K>::value && is_etl_expr<C>::value, "Convolution only supported for ETL expressions");
    check_conv_1d_sizes<3>(input, kernel, conv);

    for(std::size_t j = 0 ; j < size(conv) ; ++j){
        double temp = 0.0;

        for(std::size_t l = j ; l <= j + size(kernel) - 1; ++l){
            temp += input[l] * kernel[j + size(kernel) - 1 - l];
        }

        conv[j] = temp;
    }

    return conv;
}

template<typename I, typename K, typename C>
static C& convolve_2d_full(const I& input, const K& kernel, C&& conv){
    static_assert(is_etl_expr<I>::value && is_etl_expr<K>::value && is_etl_expr<C>::value, "Convolution only supported for ETL expressions");
    check_conv_2d_sizes<1>(input, kernel, conv);

    for(std::size_t i = 0 ; i < rows(conv) ; ++i){
        auto k_lo = std::max<int>(0, i - rows(kernel) + 1);
        auto k_hi = std::min(rows(input) - 1, i);

        for(std::size_t j = 0 ; j < columns(conv) ; ++j){
            auto l_lo = std::max<int>(0, j - columns(kernel) + 1);
            auto l_hi = std::min(columns(input) - 1 ,j);

            double temp = 0.0;

            for(std::size_t k = k_lo ; k <= k_hi ; ++k){
                for(std::size_t l = l_lo ; l <= l_hi ; ++l){
                    temp += input(k,l) * kernel(i - k, j - l);
                }
            }

            conv(i, j) = temp;
        }
    }

    return conv;
}

template<typename I, typename K, typename C>
static C& convolve_2d_same(const I& input, const K& kernel, C&& conv){
    static_assert(is_etl_expr<I>::value && is_etl_expr<K>::value && is_etl_expr<C>::value, "Convolution only supported for ETL expressions");
    check_conv_2d_sizes<2>(input, kernel, conv);

    for(std::size_t i = 0 ; i < rows(conv); ++i){
        auto k_lo = std::max<int>(0, i - (rows(kernel)-1)/2);
        auto k_hi = std::min<int>(rows(input) - 1, i + rows(kernel)/2);

        for(std::size_t j = 0 ; j < columns(conv); ++j){
            auto l_lo = std::max<int>(0, j - (columns(kernel)-1)/2);
            auto l_hi = std::min<int>(columns(input) - 1, j + columns(kernel)/2);

            double temp = 0.0;

            for(int k = k_lo ; k <= k_hi ; ++k){
                for(std::size_t l = l_lo ; l <= static_cast<std::size_t>(l_hi); ++l){
                    temp += input(k, l) * kernel(i-k+rows(kernel)/2, j-l+columns(kernel)/2);
                }
            }

            conv(i, j) = temp;
        }
    }

    return conv;
}

template<typename I, typename K, typename C>
static C& convolve_2d_valid(const I& input, const K& kernel, C&& conv){
    static_assert(is_etl_expr<I>::value && is_etl_expr<K>::value && is_etl_expr<C>::value, "Convolution only supported for ETL expressions");
    check_conv_2d_sizes<3>(input, kernel, conv);

    for(std::size_t i = 0 ; i < rows(conv) ; ++i){
        for(std::size_t j = 0 ; j < columns(conv) ; ++j){
            double temp = 0.0;

            for(std::size_t k = i ; k <= i + rows(kernel)-1; ++k){
                for(std::size_t l = j ; l <= j + columns(kernel)-1 ; ++l){
                    temp += input(k,l) * kernel((i+rows(kernel)-1-k), (j+columns(kernel)-1-l));
                }
            }

            conv(i,j) = temp;
        }
    }

    return conv;
}

} //end of namespace etl

#endif
<|endoftext|>


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

#ifndef ETL_FAST_MATRIX_HPP
#define ETL_FAST_MATRIX_HPP

#include<array>
#include<string>

#include "cpp_utils/assert.hpp"

#include "tmp.hpp"
#include "traits_fwd.hpp"

namespace etl {

namespace matrix_detail {

template<typename M, std::size_t I, typename Enable = void>
struct matrix_subsize  : std::integral_constant<std::size_t, M::template dim<I+1>() * matrix_subsize<M, I+1>::value> {};

template<typename M, std::size_t I>
struct matrix_subsize<M, I, std::enable_if_t<I == M::n_dimensions - 1>> : std::integral_constant<std::size_t, 1> {};

template<typename M, std::size_t I, std::size_t Stop, typename S1, typename... S>
struct matrix_index {
    template<std::size_t I2, typename Enable = void>
    struct matrix_index_int {
        static std::size_t compute(S1 first, S... args){
            cpp_assert(first < M::template dim<I2>(), "Out of bounds");

            return matrix_subsize<M, I>::value * first + matrix_index<M, I+1, Stop, S...>::compute(args...);
        }
    };

    template<std::size_t I2>
    struct matrix_index_int<I2, std::enable_if_t<I2 == Stop>> {
        static std::size_t compute(S1 first){
            cpp_assert(first < M::template dim<I2>(), "Out of bounds");

            return first;
        }
    };

    static std::size_t compute(S1 first, S... args){
        return matrix_index_int<I>::compute(first, args...);
    }
};

} //end of namespace detail

template<typename T, std::size_t... Dims>
struct fast_matrix {
    static_assert(sizeof...(Dims) > 0, "At least one dimension must be specified");

public:
    static constexpr const std::size_t n_dimensions = sizeof...(Dims);
    static constexpr const std::size_t etl_size = mul_all<Dims...>::value;

    using       value_type = T;
    using     storage_impl = std::array<value_type, etl_size>;
    using         iterator = typename storage_impl::iterator;
    using   const_iterator = typename storage_impl::const_iterator;
    using        this_type = fast_matrix<T, Dims...>;

private:
    storage_impl _data;

    template<typename... S>
    static constexpr std::size_t index(S... args){
        return matrix_detail::matrix_index<this_type, 0, n_dimensions - 1, S...>::compute(args...);
    }

    template<typename... S>
    value_type& access(S... args){
        return _data[index(args...)];
    }

    template<typename... S>
    const value_type& access(S... args) const {
        return _data[index(args...)];
    }

public:

    ///{{{ Construction

    fast_matrix(){
        //Nothing to init
    }

    template<typename VT, cpp::enable_if_u<cpp::or_u<std::is_convertible<VT, value_type>::value, std::is_assignable<T&, VT>::value>::value> = cpp::detail::dummy>
    explicit fast_matrix(const VT& value){
        std::fill(_data.begin(), _data.end(), value);
    }

    fast_matrix(std::initializer_list<value_type> l){
        cpp_assert(l.size() == size(), "Cannot copy from an initializer of different size");

        std::copy(l.begin(), l.end(), begin());
    }

    explicit fast_matrix(const fast_matrix& rhs){
        std::copy(rhs.begin(), rhs.end(), begin());
    }

    fast_matrix(fast_matrix&& rhs){
        std::copy(rhs.begin(), rhs.end(), begin());
    }

    template<typename LE, typename Op, typename RE>
    explicit fast_matrix(const binary_expr<value_type, LE, Op, RE>& e){
        ensure_same_size(*this, e);

        for(std::size_t i = 0; i < size(); ++i){
            _data[i] = e[i];
        }
    }

    template<typename E, typename Op>
    explicit fast_matrix(const unary_expr<value_type, E, Op>& e){
        ensure_same_size(*this, e);

        for(std::size_t i = 0; i < size(); ++i){
            _data[i] = e[i];
        }
    }

    template<typename Expr>
    explicit fast_matrix(const stable_transform_expr<value_type, Expr>& e){
        ensure_same_size(*this, e);

        for(std::size_t i = 0; i < size(); ++i){
            _data[i] = e[i];
        }
    }

    template<typename Generator>
    explicit fast_matrix(generator_expr<Generator>&& e){
        for(std::size_t i = 0; i < size(); ++i){
            _data[i] = e[i];
        }
    }

    template<typename E, cpp::enable_if_u<etl_traits<unstable_transform_expr<value_type, E>>::dimensions() == 1> = cpp::detail::dummy>
    explicit fast_matrix(const unstable_transform_expr<value_type, E>& e){
        static_assert(n_dimensions == 1, "Transform expressions are only 1D-valid for now");

        ensure_same_size(*this, e);

        for(std::size_t i = 0; i < dim<0>(); ++i){
            _data[index(i)] = e(i);
        }
    }

    template<typename E, cpp::enable_if_u<etl_traits<unstable_transform_expr<value_type, E>>::dimensions() == 2> = cpp::detail::dummy>
    explicit fast_matrix(const unstable_transform_expr<value_type, E>& e){
        static_assert(n_dimensions == 2, "Transform expressions are only 2D-valid for now");

        ensure_same_size(*this, e);

        for(std::size_t i = 0; i < dim<0>(); ++i){
            for(std::size_t j = 0; j < dim<1>(); ++j){
                _data[index(i,j)] = e(i,j);
            }
        }
    }

    template<typename E, cpp::enable_if_u<etl_traits<unstable_transform_expr<value_type, E>>::dimensions() == 3> = cpp::detail::dummy>
    explicit fast_matrix(const unstable_transform_expr<value_type, E>& e){
        static_assert(n_dimensions == 3, "Transform expressions are only 3D-valid for now");

        ensure_same_size(*this, e);

        for(std::size_t i = 0; i < dim<0>(); ++i){
            for(std::size_t j = 0; j < dim<1>(); ++j){
                for(std::size_t k = 0; k < dim<2>(); ++k){
                    _data[index(i,j,k)] = e(i,j,k);
                }
            }
        }
    }

    //}}}

    //{{{ Assignment

    //Copy assignment operator

    fast_matrix& operator=(const fast_matrix& rhs){
        std::copy(rhs.begin(), rhs.end(), begin());

        return *this;
    }

    //Allow copy from other containers

    template<typename Container, cpp::enable_if_u<std::is_same<typename Container::value_type, value_type>::value> = cpp::detail::dummy>
    fast_matrix& operator=(const Container& vec){
        std::copy(vec.begin(), vec.end(), begin());

        return *this;
    }

    //Construct from expression

    template<typename LE, typename Op, typename RE>
    fast_matrix& operator=(binary_expr<value_type, LE, Op, RE>&& e){
        ensure_same_size(*this, e);

        for(std::size_t i = 0; i < size(); ++i){
            _data[i] = e[i];
        }

        return *this;
    }

    template<typename E, typename Op>
    fast_matrix& operator=(unary_expr<value_type, E, Op>&& e){
        ensure_same_size(*this, e);

        for(std::size_t i = 0; i < size(); ++i){
            _data[i] = e[i];
        }

        return *this;
    }

    template<typename Expr>
    fast_matrix& operator=(stable_transform_expr<value_type, Expr>&& e){
        ensure_same_size(*this, e);

        for(std::size_t i = 0; i < size(); ++i){
            _data[i] = e[i];
        }

        return *this;
    }

    template<typename E, cpp::enable_if_u<etl_traits<unstable_transform_expr<value_type, E>>::dimensions() == 1> = cpp::detail::dummy>
    fast_matrix& operator=(unstable_transform_expr<value_type, E>&& e){
        ensure_same_size(*this, e);

        for(std::size_t i = 0; i < dim<0>(); ++i){
            _data[index(i)] = e(i);
        }

        return *this;
    }

    template<typename E, cpp::enable_if_u<etl_traits<unstable_transform_expr<value_type, E>>::dimensions() == 2> = cpp::detail::dummy>
    fast_matrix& operator=(unstable_transform_expr<value_type, E>&& e){
        ensure_same_size(*this, e);

        for(std::size_t i = 0; i < dim<0>(); ++i){
            for(std::size_t j = 0; j < dim<1>(); ++j){
                _data[index(i,j)] = e(i,j);
            }
        }

        return *this;
    }

    template<typename E, cpp::enable_if_u<etl_traits<unstable_transform_expr<value_type, E>>::dimensions() == 3> = cpp::detail::dummy>
    fast_matrix& operator=(unstable_transform_expr<value_type, E>&& e){
        ensure_same_size(*this, e);

        for(std::size_t i = 0; i < dim<0>(); ++i){
            for(std::size_t j = 0; j < dim<1>(); ++j){
                for(std::size_t k = 0; k < dim<2>(); ++k){
                    _data[index(i,j,k)] = e(i,j,k);
                }
            }
        }

        return *this;
    }

    template<typename Generator>
    fast_matrix& operator=(generator_expr<Generator>&& e){
        for(std::size_t i = 0; i < size(); ++i){
            _data[i] = e[i];
        }

        return *this;
    }

    //Set the same value to each element of the matrix
    template<typename VT, cpp::enable_if_u<cpp::or_u<std::is_convertible<VT, value_type>::value, std::is_assignable<T&, VT>::value>::value> = cpp::detail::dummy>
    fast_matrix& operator=(const VT& value){
        std::fill(_data.begin(), _data.end(), value);

        return *this;
    }

    //Prohibit move
    fast_matrix& operator=(fast_matrix&& rhs) = delete;

    //}}}

    //{{{ Accessors

    static constexpr std::size_t size(){
        return etl_size;
    }

    static constexpr std::size_t rows(){
        return dim<0>();
    }

    static constexpr std::size_t columns(){
        static_assert(n_dimensions > 1, "columns() can only be used on 2D+ matrices");

        return dim<1>();
    }

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

    template<std::size_t D>
    static constexpr std::size_t dim(){
        return nth_size<D, 0, Dims...>::value;
    }

    //TODO Would probably be useful to have dim(std::size_t i)

    template<bool B = (n_dimensions > 1), cpp::enable_if_u<B> = cpp::detail::dummy>
    auto operator()(std::size_t i){
        return sub(*this, i);
    }

    template<bool B = (n_dimensions > 1), cpp::enable_if_u<B> = cpp::detail::dummy>
    auto operator()(std::size_t i) const {
        return sub(*this, i);
    }

    template<typename... S>
    std::enable_if_t<sizeof...(S) == sizeof...(Dims), value_type&> operator()(S... args){
        static_assert(cpp::all_convertible_to<std::size_t, S...>::value, "Invalid size types");

        return access(static_cast<std::size_t>(args)...);
    }

    template<typename... S>
    std::enable_if_t<sizeof...(S) == sizeof...(Dims), const value_type&> operator()(S... args) const {
        static_assert(cpp::all_convertible_to<std::size_t, S...>::value, "Invalid size types");

        return access(static_cast<std::size_t>(args)...);
    }

    const value_type& operator[](std::size_t i) const {
        cpp_assert(i < size(), "Out of bounds");

        return _data[i];
    }

    value_type& operator[](std::size_t i){
        cpp_assert(i < size(), "Out of bounds");

        return _data[i];
    }

    const_iterator begin() const {
        return _data.begin();
    }

    const_iterator end() const {
        return _data.end();
    }

    iterator begin(){
        return _data.begin();
    }

    iterator end(){
        return _data.end();
    }

    //}}}
};

} //end of namespace etl

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

#ifndef ETL_FAST_MATRIX_HPP
#define ETL_FAST_MATRIX_HPP

#include<array>
#include<string>

#include "cpp_utils/assert.hpp"

#include "tmp.hpp"
#include "traits_fwd.hpp"

namespace etl {

namespace matrix_detail {

template<typename M, std::size_t I, typename Enable = void>
struct matrix_subsize  : std::integral_constant<std::size_t, M::template dim<I+1>() * matrix_subsize<M, I+1>::value> {};

template<typename M, std::size_t I>
struct matrix_subsize<M, I, std::enable_if_t<I == M::n_dimensions - 1>> : std::integral_constant<std::size_t, 1> {};

template<typename M, std::size_t I, std::size_t Stop, typename S1, typename... S>
struct matrix_index {
    template<std::size_t I2, typename Enable = void>
    struct matrix_index_int {
        static std::size_t compute(S1 first, S... args){
            cpp_assert(first < M::template dim<I2>(), "Out of bounds");

            return matrix_subsize<M, I>::value * first + matrix_index<M, I+1, Stop, S...>::compute(args...);
        }
    };

    template<std::size_t I2>
    struct matrix_index_int<I2, std::enable_if_t<I2 == Stop>> {
        static std::size_t compute(S1 first){
            cpp_assert(first < M::template dim<I2>(), "Out of bounds");

            return first;
        }
    };

    static std::size_t compute(S1 first, S... args){
        return matrix_index_int<I>::compute(first, args...);
    }
};

} //end of namespace detail

template<typename T, std::size_t... Dims>
struct fast_matrix {
    static_assert(sizeof...(Dims) > 0, "At least one dimension must be specified");

public:
    static constexpr const std::size_t n_dimensions = sizeof...(Dims);
    static constexpr const std::size_t etl_size = mul_all<Dims...>::value;

    using       value_type = T;
    using     storage_impl = std::array<value_type, etl_size>;
    using         iterator = typename storage_impl::iterator;
    using   const_iterator = typename storage_impl::const_iterator;
    using        this_type = fast_matrix<T, Dims...>;

private:
    storage_impl _data;

    template<typename... S>
    static constexpr std::size_t index(S... args){
        return matrix_detail::matrix_index<this_type, 0, n_dimensions - 1, S...>::compute(args...);
    }

    template<typename... S>
    value_type& access(S... args){
        return _data[index(args...)];
    }

    template<typename... S>
    const value_type& access(S... args) const {
        return _data[index(args...)];
    }

public:

    ///{{{ Construction

    fast_matrix(){
        //Nothing to init
    }

    template<typename VT, cpp::enable_if_u<cpp::or_u<std::is_convertible<VT, value_type>::value, std::is_assignable<T&, VT>::value>::value> = cpp::detail::dummy>
    explicit fast_matrix(const VT& value){
        std::fill(_data.begin(), _data.end(), value);
    }

    fast_matrix(std::initializer_list<value_type> l){
        cpp_assert(l.size() == size(), "Cannot copy from an initializer of different size");

        std::copy(l.begin(), l.end(), begin());
    }

    explicit fast_matrix(const fast_matrix& rhs){
        std::copy(rhs.begin(), rhs.end(), begin());
    }

    fast_matrix(fast_matrix&& rhs){
        std::copy(rhs.begin(), rhs.end(), begin());
    }

    template<typename E, cpp::enable_if_all_u<
        std::is_convertible<typename E::value_type, value_type>::value,
        is_copy_expr<E>::value
    > = cpp::detail::dummy>
    explicit fast_matrix(const E& e){
        ensure_same_size(*this, e);

        for(std::size_t i = 0; i < size(); ++i){
            _data[i] = e[i];
        }
    }

    template<typename Generator>
    explicit fast_matrix(generator_expr<Generator>&& e){
        for(std::size_t i = 0; i < size(); ++i){
            _data[i] = e[i];
        }
    }

    template<typename E, cpp::enable_if_u<etl_traits<unstable_transform_expr<value_type, E>>::dimensions() == 1> = cpp::detail::dummy>
    explicit fast_matrix(const unstable_transform_expr<value_type, E>& e){
        static_assert(n_dimensions == 1, "Transform expressions are only 1D-valid for now");

        ensure_same_size(*this, e);

        for(std::size_t i = 0; i < dim<0>(); ++i){
            _data[index(i)] = e(i);
        }
    }

    template<typename E, cpp::enable_if_u<etl_traits<unstable_transform_expr<value_type, E>>::dimensions() == 2> = cpp::detail::dummy>
    explicit fast_matrix(const unstable_transform_expr<value_type, E>& e){
        static_assert(n_dimensions == 2, "Transform expressions are only 2D-valid for now");

        ensure_same_size(*this, e);

        for(std::size_t i = 0; i < dim<0>(); ++i){
            for(std::size_t j = 0; j < dim<1>(); ++j){
                _data[index(i,j)] = e(i,j);
            }
        }
    }

    template<typename E, cpp::enable_if_u<etl_traits<unstable_transform_expr<value_type, E>>::dimensions() == 3> = cpp::detail::dummy>
    explicit fast_matrix(const unstable_transform_expr<value_type, E>& e){
        static_assert(n_dimensions == 3, "Transform expressions are only 3D-valid for now");

        ensure_same_size(*this, e);

        for(std::size_t i = 0; i < dim<0>(); ++i){
            for(std::size_t j = 0; j < dim<1>(); ++j){
                for(std::size_t k = 0; k < dim<2>(); ++k){
                    _data[index(i,j,k)] = e(i,j,k);
                }
            }
        }
    }

    //}}}

    //{{{ Assignment

    //Copy assignment operator

    fast_matrix& operator=(const fast_matrix& rhs){
        std::copy(rhs.begin(), rhs.end(), begin());

        return *this;
    }

    //Allow copy from other containers

    template<typename Container, cpp::enable_if_u<std::is_same<typename Container::value_type, value_type>::value> = cpp::detail::dummy>
    fast_matrix& operator=(const Container& vec){
        std::copy(vec.begin(), vec.end(), begin());

        return *this;
    }

    //Construct from expression

    template<typename E, cpp::enable_if_all_u<
        std::is_convertible<typename E::value_type, value_type>::value,
        is_copy_expr<E>::value
    > = cpp::detail::dummy>
    fast_matrix& operator=(E&& e){
        ensure_same_size(*this, e);

        for(std::size_t i = 0; i < size(); ++i){
            _data[i] = e[i];
        }

        return *this;
    }

    template<typename Generator>
    fast_matrix& operator=(generator_expr<Generator>&& e){
        for(std::size_t i = 0; i < size(); ++i){
            _data[i] = e[i];
        }

        return *this;
    }

    template<typename E, cpp::enable_if_u<etl_traits<unstable_transform_expr<value_type, E>>::dimensions() == 1> = cpp::detail::dummy>
    fast_matrix& operator=(unstable_transform_expr<value_type, E>&& e){
        ensure_same_size(*this, e);

        for(std::size_t i = 0; i < dim<0>(); ++i){
            _data[index(i)] = e(i);
        }

        return *this;
    }

    template<typename E, cpp::enable_if_u<etl_traits<unstable_transform_expr<value_type, E>>::dimensions() == 2> = cpp::detail::dummy>
    fast_matrix& operator=(unstable_transform_expr<value_type, E>&& e){
        ensure_same_size(*this, e);

        for(std::size_t i = 0; i < dim<0>(); ++i){
            for(std::size_t j = 0; j < dim<1>(); ++j){
                _data[index(i,j)] = e(i,j);
            }
        }

        return *this;
    }

    template<typename E, cpp::enable_if_u<etl_traits<unstable_transform_expr<value_type, E>>::dimensions() == 3> = cpp::detail::dummy>
    fast_matrix& operator=(unstable_transform_expr<value_type, E>&& e){
        ensure_same_size(*this, e);

        for(std::size_t i = 0; i < dim<0>(); ++i){
            for(std::size_t j = 0; j < dim<1>(); ++j){
                for(std::size_t k = 0; k < dim<2>(); ++k){
                    _data[index(i,j,k)] = e(i,j,k);
                }
            }
        }

        return *this;
    }

    //Set the same value to each element of the matrix
    template<typename VT, cpp::enable_if_u<cpp::or_u<std::is_convertible<VT, value_type>::value, std::is_assignable<T&, VT>::value>::value> = cpp::detail::dummy>
    fast_matrix& operator=(const VT& value){
        std::fill(_data.begin(), _data.end(), value);

        return *this;
    }

    //Prohibit move
    fast_matrix& operator=(fast_matrix&& rhs) = delete;

    //}}}

    //{{{ Accessors

    static constexpr std::size_t size(){
        return etl_size;
    }

    static constexpr std::size_t rows(){
        return dim<0>();
    }

    static constexpr std::size_t columns(){
        static_assert(n_dimensions > 1, "columns() can only be used on 2D+ matrices");

        return dim<1>();
    }

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

    template<std::size_t D>
    static constexpr std::size_t dim(){
        return nth_size<D, 0, Dims...>::value;
    }

    //TODO Would probably be useful to have dim(std::size_t i)

    template<bool B = (n_dimensions > 1), cpp::enable_if_u<B> = cpp::detail::dummy>
    auto operator()(std::size_t i){
        return sub(*this, i);
    }

    template<bool B = (n_dimensions > 1), cpp::enable_if_u<B> = cpp::detail::dummy>
    auto operator()(std::size_t i) const {
        return sub(*this, i);
    }

    template<typename... S>
    std::enable_if_t<sizeof...(S) == sizeof...(Dims), value_type&> operator()(S... args){
        static_assert(cpp::all_convertible_to<std::size_t, S...>::value, "Invalid size types");

        return access(static_cast<std::size_t>(args)...);
    }

    template<typename... S>
    std::enable_if_t<sizeof...(S) == sizeof...(Dims), const value_type&> operator()(S... args) const {
        static_assert(cpp::all_convertible_to<std::size_t, S...>::value, "Invalid size types");

        return access(static_cast<std::size_t>(args)...);
    }

    const value_type& operator[](std::size_t i) const {
        cpp_assert(i < size(), "Out of bounds");

        return _data[i];
    }

    value_type& operator[](std::size_t i){
        cpp_assert(i < size(), "Out of bounds");

        return _data[i];
    }

    const_iterator begin() const {
        return _data.begin();
    }

    const_iterator end() const {
        return _data.end();
    }

    iterator begin(){
        return _data.begin();
    }

    iterator end(){
        return _data.end();
    }

    //}}}
};

} //end of namespace etl

#endif
<|endoftext|>


<commit_before>//
//  inpal_algorithm.hpp
//  Inverse Palindrome Library
//
//  Created by Bryan Triana on 7/22/16.
//  Copyright © 2016 Inverse Palindrome. All rights reserved.
//

#ifndef inpal_algorithm_hpp
#define inpal_algorithm_hpp
#include <cstdlib>

namespace inpal
{
   namespace algorithm
    {
        std::size_t modulo(std::size_t a, std::size_t b, std::size_t c);
        std::size_t mulmod(std::size_t a, std::size_t b, std::size_t c);
        bool pal_test(std::size_t num);
    }
}

#endif /* inpal_algorithm_hpp */

<commit_msg>Update inpal_algorithm.hpp<commit_after>//
//  inpal_algorithm.hpp
//  Inverse Palindrome Library
//
//  Created by Bryan Triana on 7/22/16.
//  Copyright © 2016 Inverse Palindrome. All rights reserved.
//

#ifndef inpal_algorithm_hpp
#define inpal_algorithm_hpp
#include <cstdlib>

namespace inpal
{
   namespace algorithm
    {
        std::size_t modulo(std::size_t a, std::size_t b, std::size_t c);
        std::size_t mulmod(std::size_t a, std::size_t b, std::size_t c);
        bool pal_test(std::size_t num);
    }
}

#endif /* inpal_algorithm_hpp */

<|endoftext|>


<commit_before>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "kernel/register.h"
#include "kernel/celltypes.h"
#include "kernel/rtlil.h"
#include "kernel/log.h"

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

struct SynthIce40Pass : public ScriptPass
{
	SynthIce40Pass() : ScriptPass("synth_ice40", "synthesis for iCE40 FPGAs") { }

	void help() YS_OVERRIDE
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    synth_ice40 [options]\n");
		log("\n");
		log("This command runs synthesis for iCE40 FPGAs.\n");
		log("\n");
		log("    -top <module>\n");
		log("        use the specified module as top module\n");
		log("\n");
		log("    -blif <file>\n");
		log("        write the design to the specified BLIF file. writing of an output file\n");
		log("        is omitted if this parameter is not specified.\n");
		log("\n");
		log("    -edif <file>\n");
		log("        write the design to the specified EDIF file. writing of an output file\n");
		log("        is omitted if this parameter is not specified.\n");
		log("\n");
		log("    -json <file>\n");
		log("        write the design to the specified JSON file. writing of an output file\n");
		log("        is omitted if this parameter is not specified.\n");
		log("\n");
		log("    -run <from_label>:<to_label>\n");
		log("        only run the commands between the labels (see below). an empty\n");
		log("        from label is synonymous to 'begin', and empty to label is\n");
		log("        synonymous to the end of the command list.\n");
		log("\n");
		log("    -noflatten\n");
		log("        do not flatten design before synthesis\n");
		log("\n");
		log("    -retime\n");
		log("        run 'abc' with -dff option\n");
		log("\n");
		log("    -relut\n");
		log("        combine LUTs after synthesis\n");
		log("\n");
		log("    -nocarry\n");
		log("        do not use SB_CARRY cells in output netlist\n");
		log("\n");
		log("    -nodffe\n");
		log("        do not use SB_DFFE* cells in output netlist\n");
		log("\n");
		log("    -dffe_min_ce_use <min_ce_use>\n");
		log("        do not use SB_DFFE* cells if the resulting CE line would go to less\n");
		log("        than min_ce_use SB_DFFE*in output netlist\n");
		log("\n");
		log("    -nobram\n");
		log("        do not use SB_RAM40_4K* cells in output netlist\n");
		log("\n");
		log("    -dsp\n");
		log("        use iCE40 UltraPlus DSP cells for large arithmetic\n");
		log("\n");
		log("    -noabc\n");
		log("        use built-in Yosys LUT techmapping instead of abc\n");
		log("\n");
		log("    -abc2\n");
		log("        run two passes of 'abc' for slightly improved logic density\n");
		log("\n");
		log("    -vpr\n");
		log("        generate an output netlist (and BLIF file) suitable for VPR\n");
		log("        (this feature is experimental and incomplete)\n");
		log("\n");
		log("\n");
		log("The following commands are executed by this synthesis command:\n");
		help_script();
		log("\n");
	}

	string top_opt, blif_file, edif_file, json_file;
	bool nocarry, nodffe, nobram, dsp, flatten, retime, relut, noabc, abc2, vpr;
	int min_ce_use;

	void clear_flags() YS_OVERRIDE
	{
		top_opt = "-auto-top";
		blif_file = "";
		edif_file = "";
		json_file = "";
		nocarry = false;
		nodffe = false;
		min_ce_use = -1;
		nobram = false;
		dsp = false;
		flatten = true;
		retime = false;
		relut = false;
		noabc = false;
		abc2 = false;
		vpr = false;
	}

	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
	{
		string run_from, run_to;
		clear_flags();

		size_t argidx;
		for (argidx = 1; argidx < args.size(); argidx++)
		{
			if (args[argidx] == "-top" && argidx+1 < args.size()) {
				top_opt = "-top " + args[++argidx];
				continue;
			}
			if (args[argidx] == "-blif" && argidx+1 < args.size()) {
				blif_file = args[++argidx];
				continue;
			}
			if (args[argidx] == "-edif" && argidx+1 < args.size()) {
				edif_file = args[++argidx];
				continue;
			}
			if (args[argidx] == "-json" && argidx+1 < args.size()) {
				json_file = args[++argidx];
				continue;
			}
			if (args[argidx] == "-run" && argidx+1 < args.size()) {
				size_t pos = args[argidx+1].find(':');
				if (pos == std::string::npos)
					break;
				run_from = args[++argidx].substr(0, pos);
				run_to = args[argidx].substr(pos+1);
				continue;
			}
			if (args[argidx] == "-flatten") {
				flatten = true;
				continue;
			}
			if (args[argidx] == "-noflatten") {
				flatten = false;
				continue;
			}
			if (args[argidx] == "-retime") {
				retime = true;
				continue;
			}
			if (args[argidx] == "-relut") {
				relut = true;
				continue;
			}
			if (args[argidx] == "-nocarry") {
				nocarry = true;
				continue;
			}
			if (args[argidx] == "-nodffe") {
				nodffe = true;
				continue;
			}
			if (args[argidx] == "-dffe_min_ce_use" && argidx+1 < args.size()) {
				min_ce_use = std::stoi(args[++argidx]);
				continue;
			}
			if (args[argidx] == "-nobram") {
				nobram = true;
				continue;
			}
			if (args[argidx] == "-dsp") {
				dsp = true;
				continue;
			}
			if (args[argidx] == "-noabc") {
				noabc = true;
				continue;
			}
			if (args[argidx] == "-abc2") {
				abc2 = true;
				continue;
			}
			if (args[argidx] == "-vpr") {
				vpr = true;
				continue;
			}
			break;
		}
		extra_args(args, argidx, design);

		if (!design->full_selection())
			log_cmd_error("This command only operates on fully selected designs!\n");

		log_header(design, "Executing SYNTH_ICE40 pass.\n");
		log_push();

		run_script(design, run_from, run_to);

		log_pop();
	}

	void script() YS_OVERRIDE
	{
		if (check_label("begin"))
		{
			run("read_verilog -lib +/ice40/cells_sim.v");
			run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
			run("proc");
		}

		if (flatten && check_label("flatten", "(unless -noflatten)"))
		{
			run("flatten");
			run("tribuf -logic");
			run("deminout");
		}

		if (check_label("coarse"))
		{
			run("opt_expr");
			run("opt_clean");
			run("check");
			run("opt");
			run("wreduce");
			run("share");
			run("techmap -map +/cmp2lut.v -D LUT_WIDTH=4");
			run("opt_expr");
			run("opt_clean");
			if (help_mode || dsp)
				run("ice40_dsp", "(if -dsp)");
			run("alumacc");
			run("opt");
			run("fsm");
			run("opt -fast");
			run("memory -nomap");
			run("opt_clean");
		}

		if (!nobram && check_label("bram", "(skip if -nobram)"))
		{
			run("memory_bram -rules +/ice40/brams.txt");
			run("techmap -map +/ice40/brams_map.v");
		}

		if (check_label("map"))
		{
			run("opt -fast -mux_undef -undriven -fine");
			run("memory_map");
			run("opt -undriven -fine");
		}

		if (check_label("map_gates"))
		{
			if (nocarry)
				run("techmap");
			else
				run("techmap -map +/techmap.v -map +/ice40/arith_map.v");
			if (retime || help_mode)
				run("abc -dff", "(only if -retime)");
			run("ice40_opt");
		}

		if (check_label("map_ffs"))
		{
			run("dffsr2dff");
			if (!nodffe)
				run("dff2dffe -direct-match $_DFF_*");
			if (min_ce_use >= 0) {
				run("opt_merge");
				run(stringf("dff2dffe -unmap-mince %d", min_ce_use));
			}
			run("techmap -D NO_LUT -map +/ice40/cells_map.v");
			run("opt_expr -mux_undef");
			run("simplemap");
			run("ice40_ffinit");
			run("ice40_ffssr");
			run("ice40_opt -full");
		}

		if (check_label("map_luts"))
		{
			if (abc2 || help_mode) {
				run("abc", "      (only if -abc2)");
				run("ice40_opt", "(only if -abc2)");
			}
			run("techmap -map +/ice40/latches_map.v");
			if (noabc || help_mode) {
				run("simplemap", "                               (only if -noabc)");
				run("techmap -map +/gate2lut.v -D LUT_WIDTH=4", "(only if -noabc)");
			}
			if (!noabc) {
				run("abc -dress -lut 4", "(skip if -noabc)");
			}
			run("clean");
			if (relut || help_mode) {
				run("ice40_unlut", "                            (only if -relut)");
				run("opt_lut -dlogic SB_CARRY:I0=1:I1=2:CI=3", "(only if -relut)");
			}
		}

		if (check_label("map_cells"))
		{
			if (vpr)
				run("techmap -D NO_LUT -map +/ice40/cells_map.v");
			else
				run("techmap -map +/ice40/cells_map.v", "(with -D NO_LUT in vpr mode)");

			run("clean");
		}

		if (check_label("check"))
		{
			run("hierarchy -check");
			run("stat");
			run("check -noinit");
		}

		if (check_label("blif"))
		{
			if (!blif_file.empty() || help_mode) {
				if (vpr || help_mode) {
					run(stringf("opt_clean -purge"),
							"                                 (vpr mode)");
					run(stringf("write_blif -attr -cname -conn -param %s",
							help_mode ? "<file-name>" : blif_file.c_str()),
							" (vpr mode)");
				}
				if (!vpr)
					run(stringf("write_blif -gates -attr -param %s",
							help_mode ? "<file-name>" : blif_file.c_str()),
							"       (non-vpr mode)");
			}
		}

		if (check_label("edif"))
		{
			if (!edif_file.empty() || help_mode)
				run(stringf("write_edif %s", help_mode ? "<file-name>" : edif_file.c_str()));
		}

		if (check_label("json"))
		{
			if (!json_file.empty() || help_mode)
				run(stringf("write_json %s", help_mode ? "<file-name>" : json_file.c_str()));
		}
	}
} SynthIce40Pass;

PRIVATE_NAMESPACE_END
<commit_msg>ice40: Run ice40_braminit pass by default<commit_after>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "kernel/register.h"
#include "kernel/celltypes.h"
#include "kernel/rtlil.h"
#include "kernel/log.h"

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

struct SynthIce40Pass : public ScriptPass
{
	SynthIce40Pass() : ScriptPass("synth_ice40", "synthesis for iCE40 FPGAs") { }

	void help() YS_OVERRIDE
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    synth_ice40 [options]\n");
		log("\n");
		log("This command runs synthesis for iCE40 FPGAs.\n");
		log("\n");
		log("    -top <module>\n");
		log("        use the specified module as top module\n");
		log("\n");
		log("    -blif <file>\n");
		log("        write the design to the specified BLIF file. writing of an output file\n");
		log("        is omitted if this parameter is not specified.\n");
		log("\n");
		log("    -edif <file>\n");
		log("        write the design to the specified EDIF file. writing of an output file\n");
		log("        is omitted if this parameter is not specified.\n");
		log("\n");
		log("    -json <file>\n");
		log("        write the design to the specified JSON file. writing of an output file\n");
		log("        is omitted if this parameter is not specified.\n");
		log("\n");
		log("    -run <from_label>:<to_label>\n");
		log("        only run the commands between the labels (see below). an empty\n");
		log("        from label is synonymous to 'begin', and empty to label is\n");
		log("        synonymous to the end of the command list.\n");
		log("\n");
		log("    -noflatten\n");
		log("        do not flatten design before synthesis\n");
		log("\n");
		log("    -retime\n");
		log("        run 'abc' with -dff option\n");
		log("\n");
		log("    -relut\n");
		log("        combine LUTs after synthesis\n");
		log("\n");
		log("    -nocarry\n");
		log("        do not use SB_CARRY cells in output netlist\n");
		log("\n");
		log("    -nodffe\n");
		log("        do not use SB_DFFE* cells in output netlist\n");
		log("\n");
		log("    -dffe_min_ce_use <min_ce_use>\n");
		log("        do not use SB_DFFE* cells if the resulting CE line would go to less\n");
		log("        than min_ce_use SB_DFFE*in output netlist\n");
		log("\n");
		log("    -nobram\n");
		log("        do not use SB_RAM40_4K* cells in output netlist\n");
		log("\n");
		log("    -dsp\n");
		log("        use iCE40 UltraPlus DSP cells for large arithmetic\n");
		log("\n");
		log("    -noabc\n");
		log("        use built-in Yosys LUT techmapping instead of abc\n");
		log("\n");
		log("    -abc2\n");
		log("        run two passes of 'abc' for slightly improved logic density\n");
		log("\n");
		log("    -vpr\n");
		log("        generate an output netlist (and BLIF file) suitable for VPR\n");
		log("        (this feature is experimental and incomplete)\n");
		log("\n");
		log("\n");
		log("The following commands are executed by this synthesis command:\n");
		help_script();
		log("\n");
	}

	string top_opt, blif_file, edif_file, json_file;
	bool nocarry, nodffe, nobram, dsp, flatten, retime, relut, noabc, abc2, vpr;
	int min_ce_use;

	void clear_flags() YS_OVERRIDE
	{
		top_opt = "-auto-top";
		blif_file = "";
		edif_file = "";
		json_file = "";
		nocarry = false;
		nodffe = false;
		min_ce_use = -1;
		nobram = false;
		dsp = false;
		flatten = true;
		retime = false;
		relut = false;
		noabc = false;
		abc2 = false;
		vpr = false;
	}

	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
	{
		string run_from, run_to;
		clear_flags();

		size_t argidx;
		for (argidx = 1; argidx < args.size(); argidx++)
		{
			if (args[argidx] == "-top" && argidx+1 < args.size()) {
				top_opt = "-top " + args[++argidx];
				continue;
			}
			if (args[argidx] == "-blif" && argidx+1 < args.size()) {
				blif_file = args[++argidx];
				continue;
			}
			if (args[argidx] == "-edif" && argidx+1 < args.size()) {
				edif_file = args[++argidx];
				continue;
			}
			if (args[argidx] == "-json" && argidx+1 < args.size()) {
				json_file = args[++argidx];
				continue;
			}
			if (args[argidx] == "-run" && argidx+1 < args.size()) {
				size_t pos = args[argidx+1].find(':');
				if (pos == std::string::npos)
					break;
				run_from = args[++argidx].substr(0, pos);
				run_to = args[argidx].substr(pos+1);
				continue;
			}
			if (args[argidx] == "-flatten") {
				flatten = true;
				continue;
			}
			if (args[argidx] == "-noflatten") {
				flatten = false;
				continue;
			}
			if (args[argidx] == "-retime") {
				retime = true;
				continue;
			}
			if (args[argidx] == "-relut") {
				relut = true;
				continue;
			}
			if (args[argidx] == "-nocarry") {
				nocarry = true;
				continue;
			}
			if (args[argidx] == "-nodffe") {
				nodffe = true;
				continue;
			}
			if (args[argidx] == "-dffe_min_ce_use" && argidx+1 < args.size()) {
				min_ce_use = std::stoi(args[++argidx]);
				continue;
			}
			if (args[argidx] == "-nobram") {
				nobram = true;
				continue;
			}
			if (args[argidx] == "-dsp") {
				dsp = true;
				continue;
			}
			if (args[argidx] == "-noabc") {
				noabc = true;
				continue;
			}
			if (args[argidx] == "-abc2") {
				abc2 = true;
				continue;
			}
			if (args[argidx] == "-vpr") {
				vpr = true;
				continue;
			}
			break;
		}
		extra_args(args, argidx, design);

		if (!design->full_selection())
			log_cmd_error("This command only operates on fully selected designs!\n");

		log_header(design, "Executing SYNTH_ICE40 pass.\n");
		log_push();

		run_script(design, run_from, run_to);

		log_pop();
	}

	void script() YS_OVERRIDE
	{
		if (check_label("begin"))
		{
			run("read_verilog -lib +/ice40/cells_sim.v");
			run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
			run("proc");
		}

		if (flatten && check_label("flatten", "(unless -noflatten)"))
		{
			run("flatten");
			run("tribuf -logic");
			run("deminout");
		}

		if (check_label("coarse"))
		{
			run("opt_expr");
			run("opt_clean");
			run("check");
			run("opt");
			run("wreduce");
			run("share");
			run("techmap -map +/cmp2lut.v -D LUT_WIDTH=4");
			run("opt_expr");
			run("opt_clean");
			if (help_mode || dsp)
				run("ice40_dsp", "(if -dsp)");
			run("alumacc");
			run("opt");
			run("fsm");
			run("opt -fast");
			run("memory -nomap");
			run("opt_clean");
		}

		if (!nobram && check_label("bram", "(skip if -nobram)"))
		{
			run("memory_bram -rules +/ice40/brams.txt");
			run("techmap -map +/ice40/brams_map.v");
			run("ice40_braminit");
		}

		if (check_label("map"))
		{
			run("opt -fast -mux_undef -undriven -fine");
			run("memory_map");
			run("opt -undriven -fine");
		}

		if (check_label("map_gates"))
		{
			if (nocarry)
				run("techmap");
			else
				run("techmap -map +/techmap.v -map +/ice40/arith_map.v");
			if (retime || help_mode)
				run("abc -dff", "(only if -retime)");
			run("ice40_opt");
		}

		if (check_label("map_ffs"))
		{
			run("dffsr2dff");
			if (!nodffe)
				run("dff2dffe -direct-match $_DFF_*");
			if (min_ce_use >= 0) {
				run("opt_merge");
				run(stringf("dff2dffe -unmap-mince %d", min_ce_use));
			}
			run("techmap -D NO_LUT -map +/ice40/cells_map.v");
			run("opt_expr -mux_undef");
			run("simplemap");
			run("ice40_ffinit");
			run("ice40_ffssr");
			run("ice40_opt -full");
		}

		if (check_label("map_luts"))
		{
			if (abc2 || help_mode) {
				run("abc", "      (only if -abc2)");
				run("ice40_opt", "(only if -abc2)");
			}
			run("techmap -map +/ice40/latches_map.v");
			if (noabc || help_mode) {
				run("simplemap", "                               (only if -noabc)");
				run("techmap -map +/gate2lut.v -D LUT_WIDTH=4", "(only if -noabc)");
			}
			if (!noabc) {
				run("abc -dress -lut 4", "(skip if -noabc)");
			}
			run("clean");
			if (relut || help_mode) {
				run("ice40_unlut", "                            (only if -relut)");
				run("opt_lut -dlogic SB_CARRY:I0=1:I1=2:CI=3", "(only if -relut)");
			}
		}

		if (check_label("map_cells"))
		{
			if (vpr)
				run("techmap -D NO_LUT -map +/ice40/cells_map.v");
			else
				run("techmap -map +/ice40/cells_map.v", "(with -D NO_LUT in vpr mode)");

			run("clean");
		}

		if (check_label("check"))
		{
			run("hierarchy -check");
			run("stat");
			run("check -noinit");
		}

		if (check_label("blif"))
		{
			if (!blif_file.empty() || help_mode) {
				if (vpr || help_mode) {
					run(stringf("opt_clean -purge"),
							"                                 (vpr mode)");
					run(stringf("write_blif -attr -cname -conn -param %s",
							help_mode ? "<file-name>" : blif_file.c_str()),
							" (vpr mode)");
				}
				if (!vpr)
					run(stringf("write_blif -gates -attr -param %s",
							help_mode ? "<file-name>" : blif_file.c_str()),
							"       (non-vpr mode)");
			}
		}

		if (check_label("edif"))
		{
			if (!edif_file.empty() || help_mode)
				run(stringf("write_edif %s", help_mode ? "<file-name>" : edif_file.c_str()));
		}

		if (check_label("json"))
		{
			if (!json_file.empty() || help_mode)
				run(stringf("write_json %s", help_mode ? "<file-name>" : json_file.c_str()));
		}
	}
} SynthIce40Pass;

PRIVATE_NAMESPACE_END
<|endoftext|>


<commit_before>#ifndef __TOOLBELT_LOGGER_HPP__
#define __TOOLBELT_LOGGER_HPP__

#include <chrono>
#include <functional>
#include <iostream>
#include <stdexcept>
#include <string>
#include <sstream>
#include <vector>

#include "format_time.hpp"

namespace toolbelt {

    enum class log_level {
        INFO,
        DEBUG,
        WARNING,
        ERROR,
        FATAL
    };

    using logger_function = std::function<void(log_level, std::string&, std::chrono::time_point<std::chrono::system_clock>)>;

    class logger {
    private:
        log_level current_log_level_;
        std::vector<logger_function> loggers_;

        template<typename T>
        auto to_string(T val) {
            std::ostringstream ss;
            ss << val;
            return ss.str();
        }

        auto merge(std::initializer_list<std::string> strings) {
            std::string result;
            for(auto& str : strings) {
                result += str;
            }
            return result;
        }
    public:
        logger(bool log_cout=true) {
            if(log_cout) {
                add([](auto loglvl, auto message, auto timestamp) {
                    auto err = loglvl == log_level::ERROR || loglvl == log_level::FATAL;

                    (err ? std::cerr : std::cout) << toolbelt::format_time(timestamp, "[%H:%M:%S]");

                    switch(loglvl) {
                        case log_level::INFO: (err ? std::cerr : std::cout) << "[INFO]"; break;
                        case log_level::DEBUG: (err ? std::cerr : std::cout) << "[DEBUG]"; break;
                        case log_level::WARNING: (err ? std::cerr : std::cout) << "[WARNING]"; break;
                        case log_level::ERROR: (err ? std::cerr : std::cout) << "[ERROR]"; break;
                        case log_level::FATAL: (err ? std::cerr : std::cout) << "[FATAL]"; break;
                    }

                    (err ? std::cerr : std::cout) << "\t" << message << std::endl;
                });
            }
        }

        void add(logger_function func) {
            loggers_.push_back(func);
        }

        template<typename... Arguments>
        void log(const Arguments&... args) {
            auto message = merge({to_string(args)...});
            auto timestamp = std::chrono::system_clock::now();

            for(auto& l : loggers_) {
                l(current_log_level_, message, timestamp);
            }

            // if log lvl was fatal, exit program
            if(current_log_level_ == log_level::FATAL) {
                throw std::runtime_error(message);
            }

            // reset log level
            current_log_level_ = log_level::INFO;
        }

        logger& operator()(log_level level) {
            current_log_level_ = level;
            return *this;
        }
    };
}

#endif
<commit_msg>change class enum values to lower case, because it looks better<commit_after>#ifndef __TOOLBELT_LOGGER_HPP__
#define __TOOLBELT_LOGGER_HPP__

#include <chrono>
#include <functional>
#include <iostream>
#include <stdexcept>
#include <string>
#include <sstream>
#include <vector>

#include "format_time.hpp"

namespace toolbelt {

    enum class log_level {
        info,
        debug,
        warning,
        error,
        fatal
    };

    using logger_function = std::function<void(log_level, std::string&, std::chrono::time_point<std::chrono::system_clock>)>;

    class logger {
    private:
        log_level current_log_level_;
        std::vector<logger_function> loggers_;

        template<typename T>
        auto to_string(T val) {
            std::ostringstream ss;
            ss << val;
            return ss.str();
        }

        auto merge(std::initializer_list<std::string> strings) {
            std::string result;
            for(auto& str : strings) {
                result += str;
            }
            return result;
        }
    public:
        logger(bool log_cout=true) {
            if(log_cout) {
                add([](auto loglvl, auto message, auto timestamp) {
                    auto err = loglvl == log_level::error || loglvl == log_level::fatal;

                    (err ? std::cerr : std::cout) << toolbelt::format_time(timestamp, "[%H:%M:%S]");

                    switch(loglvl) {
                        case log_level::info: (err ? std::cerr : std::cout) << "[INFO]"; break;
                        case log_level::debug: (err ? std::cerr : std::cout) << "[DEBUG]"; break;
                        case log_level::warning: (err ? std::cerr : std::cout) << "[WARNING]"; break;
                        case log_level::error: (err ? std::cerr : std::cout) << "[ERROR]"; break;
                        case log_level::fatal: (err ? std::cerr : std::cout) << "[FATAL]"; break;
                    }

                    (err ? std::cerr : std::cout) << "\t" << message << std::endl;
                });
            }
        }

        void add(logger_function func) {
            loggers_.push_back(func);
        }

        template<typename... Arguments>
        void log(const Arguments&... args) {
            auto message = merge({to_string(args)...});
            auto timestamp = std::chrono::system_clock::now();

            for(auto& l : loggers_) {
                l(current_log_level_, message, timestamp);
            }

            // if log lvl was fatal, exit program
            if(current_log_level_ == log_level::fatal) {
                throw std::runtime_error(message);
            }

            // reset log level
            current_log_level_ = log_level::info;
        }

        logger& operator()(log_level level) {
            current_log_level_ = level;
            return *this;
        }
    };
}

#endif
<|endoftext|>


<commit_before><commit_msg>build error: specialization in different namespace<commit_after><|endoftext|>


<commit_before>#include<iostream>
using namespace std;
int main() {
    char isinilai,pil;
    int total=0;
    int i,j,p,l,x,y,z;
    cout << "=========================" << endl;
    cout << "APLIKASI RATA-RATA DGN ARRAY " << endl;
    cout << "=========================" << endl;
    cout << "Nama   : I Wayan Dharmana"  << endl;
    cout << "NIM    : 150030432"  << endl;
    cout << "Kelas  : BB153"  << endl;
    cout << "=========================" << endl;
    do{
        // System meminta user untuk memasukan nilai p (panjang)
        cout<<"Masukkan panjang: ";
        cin>>p;
        // System meminta user untuk memasukan nilai l (lebar)
        cout<<"Masukkan lebar: ";
        cin>>l;
        // Mendefinisikan panjang dan lebar array berdasarkan input user
        int angka[p][l];
        for(i=0; i<p; i++) {
            total = 0;
            for(j=0; j<l; j++) {
                angka[i][j] = 0;
            }
        }
        isinilai='y';
        cout<<"Anda ingin mengisi nilai array? (Y/N)"  << endl;
        cin>>isinilai;
        while(isinilai=='y'){
            cout<<"Masukkan posisi x (0-" << p-1 << ") : ";
            cin>>x;
            cout<<"Masukkan posisi y (0-" << l-1 << ") : ";
            cin>>y;
            cout<<"Masukkan nilai di posisi " << x << "," << y << " : ";
            cin>>z;
            angka[x][y] = z;
            cout<<"Anda ingin mengisi nilai array? (Y/N)"  << endl;
            cin>>isinilai;
        }
        for(i=0; i<p; i++) {
            total = 0;
            for(j=0; j<l; j++) {
                total = total+angka[i][j];
            }
            cout << "----------------------------------" << endl;
            cout << "|| Rata-rata baris ke-" << i << ": " << (double) total / l  << endl;
        }
        cout << "----------------------------------" << endl;
        cout<<"Anda ingin melanjutkan? (Y/N)"  << endl;
        cin>>pil;
        cout << "----------------------------------" << endl;
    }
    while(pil=='Y' || pil=='y');
    return 0;
}
<commit_msg>Update rata-rata-array.cpp<commit_after>#include<iostream>
using namespace std;
int main() {
    char isinilai,pil;
    int total=0;
    int i,j,p,l,x,y,z;
    cout << "=========================" << endl;
    cout << "APLIKASI RATA-RATA DGN ARRAY " << endl;
    cout << "=========================" << endl;
    cout << "Nama   : I Wayan Dharmana"  << endl;
    cout << "NIM    : 150030432"  << endl;
    cout << "Kelas  : BB153"  << endl;
    cout << "=========================" << endl;
    do{
        cout<<"Masukkan panjang: ";
        cin>>p;
        cout<<"Masukkan lebar: ";
        cin>>l;
        int angka[l][p];
        for(i=0; i<l; i++) {
            total = 0;
            for(j=0; j<p; j++) {
                angka[i][j] = 0;
            }
        }
        isinilai='y';
        cout<<"Anda ingin mengisi nilai array? (Y/N)"  << endl;
        cin>>isinilai;
        while(isinilai=='y'){
            cout<<"Masukkan posisi x (0-" << p-1 << ") : ";
            cin>>x;
            cout<<"Masukkan posisi y (0-" << l-1 << ") : ";
            cin>>y;
            cout<<"Masukkan nilai di posisi " << x << "," << y << " : ";
            cin>>z;
            angka[x][y] = z;
            cout<<"Anda ingin mengisi nilai array? (Y/N)"  << endl;
            cin>>isinilai;
        }
        for(i=0; i<l; i++) {
            total = 0;
            for(j=0; j<p; j++) {
                total = total+angka[i][j];
            }
            cout << "----------------------------------" << endl;
            cout << "|| Rata-rata baris ke-" << i << ": " << (double) total / l  << endl;
        }
        cout << "----------------------------------" << endl;
        cout<<"Anda ingin melanjutkan? (Y/N)"  << endl;
        cin>>pil;
        cout << "----------------------------------" << endl;
    }
    while(pil=='Y' || pil=='y');
    return 0;
}
<|endoftext|>


<commit_before>//===-- gccas.cpp - The "optimizing assembler" used by the GCC frontend ---===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This utility is designed to be used by the GCC frontend for creating bytecode
// files from its intermediate LLVM assembly.  The requirements for this utility
// are thus slightly different than that of the standard `as' util.
//
//===----------------------------------------------------------------------===//

#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Analysis/LoadValueNumbering.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Assembly/Parser.h"
#include "llvm/Bytecode/WriteBytecodePass.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/System/Signals.h"
#include <memory>
#include <fstream>

using namespace llvm;

namespace {
  cl::opt<std::string>
  InputFilename(cl::Positional,cl::desc("<input llvm assembly>"),cl::init("-"));

  cl::opt<std::string>
  OutputFilename("o", cl::desc("Override output filename"),
                 cl::value_desc("filename"));

  cl::opt<bool>
  Verify("verify", cl::desc("Verify each pass result"));

  cl::opt<bool>
  DisableInline("disable-inlining", cl::desc("Do not run the inliner pass"));

  cl::opt<bool>
  DisableOptimizations("disable-opt",
                       cl::desc("Do not run any optimization passes"));

  cl::opt<bool>
  StripDebug("strip-debug",
             cl::desc("Strip debugger symbol info from translation unit"));

  cl::opt<bool>
  NoCompress("disable-compression", cl::init(false),
             cl::desc("Don't ompress the generated bytecode"));
}

static inline void addPass(PassManager &PM, Pass *P) {
  // Add the pass to the pass manager...
  PM.add(P);

  // If we are verifying all of the intermediate steps, add the verifier...
  if (Verify) PM.add(createVerifierPass());
}

void AddConfiguredTransformationPasses(PassManager &PM) {
  PM.add(createVerifierPass());                  // Verify that input is correct

  addPass(PM, createLowerSetJmpPass());          // Lower llvm.setjmp/.longjmp
  addPass(PM, createFunctionResolvingPass());    // Resolve (...) functions

  // If the -strip-debug command line option was specified, do it.
  if (StripDebug)
    addPass(PM, createStripSymbolsPass(true));

  if (DisableOptimizations) return;

  addPass(PM, createRaiseAllocationsPass());     // call %malloc -> malloc inst
  addPass(PM, createCFGSimplificationPass());    // Clean up disgusting code
  addPass(PM, createPromoteMemoryToRegister());  // Kill useless allocas
  addPass(PM, createGlobalOptimizerPass());      // Optimize out global vars
  addPass(PM, createGlobalDCEPass());            // Remove unused fns and globs
  addPass(PM, createIPConstantPropagationPass());// IP Constant Propagation
  addPass(PM, createDeadArgEliminationPass());   // Dead argument elimination
  addPass(PM, createInstructionCombiningPass()); // Clean up after IPCP & DAE
  addPass(PM, createCFGSimplificationPass());    // Clean up after IPCP & DAE

  addPass(PM, createPruneEHPass());              // Remove dead EH info

  if (!DisableInline)
    addPass(PM, createFunctionInliningPass());   // Inline small functions
  addPass(PM, createArgumentPromotionPass());    // Scalarize uninlined fn args

  addPass(PM, createRaisePointerReferencesPass());// Recover type information
  addPass(PM, createTailDuplicationPass());      // Simplify cfg by copying code
  addPass(PM, createCFGSimplificationPass());    // Merge & remove BBs
  addPass(PM, createScalarReplAggregatesPass()); // Break up aggregate allocas
  addPass(PM, createInstructionCombiningPass()); // Combine silly seq's

  addPass(PM, createReassociatePass());          // Reassociate expressions
  addPass(PM, createInstructionCombiningPass()); // Combine silly seq's
  addPass(PM, createTailCallEliminationPass());  // Eliminate tail calls
  addPass(PM, createCFGSimplificationPass());    // Merge & remove BBs
  addPass(PM, createLICMPass());                 // Hoist loop invariants
  addPass(PM, createInstructionCombiningPass()); // Clean up after the unroller
  addPass(PM, createIndVarSimplifyPass());       // Canonicalize indvars
  addPass(PM, createLoopUnrollPass());           // Unroll small loops
  addPass(PM, createInstructionCombiningPass()); // Clean up after the unroller
  addPass(PM, createLoadValueNumberingPass());   // GVN for load instructions
  addPass(PM, createGCSEPass());                 // Remove common subexprs
  addPass(PM, createSCCPPass());                 // Constant prop with SCCP

  // Run instcombine after redundancy elimination to exploit opportunities
  // opened up by them.
  addPass(PM, createInstructionCombiningPass());
  addPass(PM, createDeadStoreEliminationPass()); // Delete dead stores
  addPass(PM, createAggressiveDCEPass());        // SSA based 'Aggressive DCE'
  addPass(PM, createCFGSimplificationPass());    // Merge & remove BBs
  addPass(PM, createDeadTypeEliminationPass());  // Eliminate dead types
  addPass(PM, createConstantMergePass());        // Merge dup global constants
}

int main(int argc, char **argv) {
  cl::ParseCommandLineOptions(argc, argv, " llvm .s -> .o assembler for GCC\n");
  sys::PrintStackTraceOnErrorSignal();

  std::auto_ptr<Module> M;
  try {
    // Parse the file now...
    M.reset(ParseAssemblyFile(InputFilename));
  } catch (const ParseException &E) {
    std::cerr << argv[0] << ": " << E.getMessage() << "\n";
    return 1;
  }

  if (M.get() == 0) {
    std::cerr << argv[0] << ": assembly didn't read correctly.\n";
    return 1;
  }

  std::ostream *Out = 0;
  if (OutputFilename == "") {   // Didn't specify an output filename?
    if (InputFilename == "-") {
      OutputFilename = "-";
    } else {
      std::string IFN = InputFilename;
      int Len = IFN.length();
      if (IFN[Len-2] == '.' && IFN[Len-1] == 's') {   // Source ends in .s?
        OutputFilename = std::string(IFN.begin(), IFN.end()-2);
      } else {
        OutputFilename = IFN;   // Append a .o to it
      }
      OutputFilename += ".o";
    }
  }

  if (OutputFilename == "-")
    Out = &std::cout;
  else {
    Out = new std::ofstream(OutputFilename.c_str(), std::ios::out);

    // Make sure that the Out file gets unlinked from the disk if we get a
    // signal
    sys::RemoveFileOnSignal(sys::Path(OutputFilename));
  }

  if (!Out->good()) {
    std::cerr << argv[0] << ": error opening " << OutputFilename << "!\n";
    return 1;
  }

  // In addition to just parsing the input from GCC, we also want to spiff it up
  // a little bit.  Do this now.
  //
  PassManager Passes;

  // Add an appropriate TargetData instance for this module...
  Passes.add(new TargetData("gccas", M.get()));

  // Add all of the transformation passes to the pass manager to do the cleanup
  // and optimization of the GCC output.
  //
  AddConfiguredTransformationPasses(Passes);

  // Make sure everything is still good.
  Passes.add(createVerifierPass());

  // Write bytecode to file...
  Passes.add(new WriteBytecodePass(Out,false,!NoCompress));

  // Run our queue of passes all at once now, efficiently.
  Passes.run(*M.get());

  if (Out != &std::cout) delete Out;
  return 0;
}
<commit_msg>Support the gas option --traditional-format which, for some reason, gets passed to gccas when the --program-prefix option is used to configure CFE.<commit_after>//===-- gccas.cpp - The "optimizing assembler" used by the GCC frontend ---===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This utility is designed to be used by the GCC frontend for creating bytecode
// files from its intermediate LLVM assembly.  The requirements for this utility
// are thus slightly different than that of the standard `as' util.
//
//===----------------------------------------------------------------------===//

#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Analysis/LoadValueNumbering.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Assembly/Parser.h"
#include "llvm/Bytecode/WriteBytecodePass.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/System/Signals.h"
#include <memory>
#include <fstream>

using namespace llvm;

namespace {
  cl::opt<std::string>
  InputFilename(cl::Positional,cl::desc("<input llvm assembly>"),cl::init("-"));

  cl::opt<std::string>
  OutputFilename("o", cl::desc("Override output filename"),
                 cl::value_desc("filename"));

  cl::opt<bool>
  Verify("verify", cl::desc("Verify each pass result"));

  cl::opt<bool>
  DisableInline("disable-inlining", cl::desc("Do not run the inliner pass"));

  cl::opt<bool>
  DisableOptimizations("disable-opt",
                       cl::desc("Do not run any optimization passes"));

  cl::opt<bool>
  StripDebug("strip-debug",
             cl::desc("Strip debugger symbol info from translation unit"));

  cl::opt<bool>
  NoCompress("disable-compression", cl::init(false),
             cl::desc("Don't ompress the generated bytecode"));

  cl::opt<bool> TF("traditional-format", cl::Hidden,
    cl::desc("Compatibility option: ignored"));
}

static inline void addPass(PassManager &PM, Pass *P) {
  // Add the pass to the pass manager...
  PM.add(P);

  // If we are verifying all of the intermediate steps, add the verifier...
  if (Verify) PM.add(createVerifierPass());
}

void AddConfiguredTransformationPasses(PassManager &PM) {
  PM.add(createVerifierPass());                  // Verify that input is correct

  addPass(PM, createLowerSetJmpPass());          // Lower llvm.setjmp/.longjmp
  addPass(PM, createFunctionResolvingPass());    // Resolve (...) functions

  // If the -strip-debug command line option was specified, do it.
  if (StripDebug)
    addPass(PM, createStripSymbolsPass(true));

  if (DisableOptimizations) return;

  addPass(PM, createRaiseAllocationsPass());     // call %malloc -> malloc inst
  addPass(PM, createCFGSimplificationPass());    // Clean up disgusting code
  addPass(PM, createPromoteMemoryToRegister());  // Kill useless allocas
  addPass(PM, createGlobalOptimizerPass());      // Optimize out global vars
  addPass(PM, createGlobalDCEPass());            // Remove unused fns and globs
  addPass(PM, createIPConstantPropagationPass());// IP Constant Propagation
  addPass(PM, createDeadArgEliminationPass());   // Dead argument elimination
  addPass(PM, createInstructionCombiningPass()); // Clean up after IPCP & DAE
  addPass(PM, createCFGSimplificationPass());    // Clean up after IPCP & DAE

  addPass(PM, createPruneEHPass());              // Remove dead EH info

  if (!DisableInline)
    addPass(PM, createFunctionInliningPass());   // Inline small functions
  addPass(PM, createArgumentPromotionPass());    // Scalarize uninlined fn args

  addPass(PM, createRaisePointerReferencesPass());// Recover type information
  addPass(PM, createTailDuplicationPass());      // Simplify cfg by copying code
  addPass(PM, createCFGSimplificationPass());    // Merge & remove BBs
  addPass(PM, createScalarReplAggregatesPass()); // Break up aggregate allocas
  addPass(PM, createInstructionCombiningPass()); // Combine silly seq's

  addPass(PM, createReassociatePass());          // Reassociate expressions
  addPass(PM, createInstructionCombiningPass()); // Combine silly seq's
  addPass(PM, createTailCallEliminationPass());  // Eliminate tail calls
  addPass(PM, createCFGSimplificationPass());    // Merge & remove BBs
  addPass(PM, createLICMPass());                 // Hoist loop invariants
  addPass(PM, createInstructionCombiningPass()); // Clean up after the unroller
  addPass(PM, createIndVarSimplifyPass());       // Canonicalize indvars
  addPass(PM, createLoopUnrollPass());           // Unroll small loops
  addPass(PM, createInstructionCombiningPass()); // Clean up after the unroller
  addPass(PM, createLoadValueNumberingPass());   // GVN for load instructions
  addPass(PM, createGCSEPass());                 // Remove common subexprs
  addPass(PM, createSCCPPass());                 // Constant prop with SCCP

  // Run instcombine after redundancy elimination to exploit opportunities
  // opened up by them.
  addPass(PM, createInstructionCombiningPass());
  addPass(PM, createDeadStoreEliminationPass()); // Delete dead stores
  addPass(PM, createAggressiveDCEPass());        // SSA based 'Aggressive DCE'
  addPass(PM, createCFGSimplificationPass());    // Merge & remove BBs
  addPass(PM, createDeadTypeEliminationPass());  // Eliminate dead types
  addPass(PM, createConstantMergePass());        // Merge dup global constants
}

int main(int argc, char **argv) {
  cl::ParseCommandLineOptions(argc, argv, " llvm .s -> .o assembler for GCC\n");
  sys::PrintStackTraceOnErrorSignal();

  std::auto_ptr<Module> M;
  try {
    // Parse the file now...
    M.reset(ParseAssemblyFile(InputFilename));
  } catch (const ParseException &E) {
    std::cerr << argv[0] << ": " << E.getMessage() << "\n";
    return 1;
  }

  if (M.get() == 0) {
    std::cerr << argv[0] << ": assembly didn't read correctly.\n";
    return 1;
  }

  std::ostream *Out = 0;
  if (OutputFilename == "") {   // Didn't specify an output filename?
    if (InputFilename == "-") {
      OutputFilename = "-";
    } else {
      std::string IFN = InputFilename;
      int Len = IFN.length();
      if (IFN[Len-2] == '.' && IFN[Len-1] == 's') {   // Source ends in .s?
        OutputFilename = std::string(IFN.begin(), IFN.end()-2);
      } else {
        OutputFilename = IFN;   // Append a .o to it
      }
      OutputFilename += ".o";
    }
  }

  if (OutputFilename == "-")
    Out = &std::cout;
  else {
    Out = new std::ofstream(OutputFilename.c_str(), std::ios::out);

    // Make sure that the Out file gets unlinked from the disk if we get a
    // signal
    sys::RemoveFileOnSignal(sys::Path(OutputFilename));
  }

  if (!Out->good()) {
    std::cerr << argv[0] << ": error opening " << OutputFilename << "!\n";
    return 1;
  }

  // In addition to just parsing the input from GCC, we also want to spiff it up
  // a little bit.  Do this now.
  //
  PassManager Passes;

  // Add an appropriate TargetData instance for this module...
  Passes.add(new TargetData("gccas", M.get()));

  // Add all of the transformation passes to the pass manager to do the cleanup
  // and optimization of the GCC output.
  //
  AddConfiguredTransformationPasses(Passes);

  // Make sure everything is still good.
  Passes.add(createVerifierPass());

  // Write bytecode to file...
  Passes.add(new WriteBytecodePass(Out,false,!NoCompress));

  // Run our queue of passes all at once now, efficiently.
  Passes.run(*M.get());

  if (Out != &std::cout) delete Out;
  return 0;
}
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
// LLVM 'GCCAS' UTILITY
//
//  This utility is designed to be used by the GCC frontend for creating
// bytecode files from it's intermediate llvm assembly.  The requirements for
// this utility are thus slightly different than that of the standard as util.
//
//===----------------------------------------------------------------------===//

#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Assembly/Parser.h"
#include "llvm/Transforms/RaisePointerReferences.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Analysis/LoadValueNumbering.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Bytecode/WriteBytecodePass.h"
#include "llvm/Target/TargetData.h"
#include "Support/CommandLine.h"
#include "Support/Signals.h"
#include <memory>
#include <fstream>

namespace {
  cl::opt<std::string>
  InputFilename(cl::Positional,cl::desc("<input llvm assembly>"),cl::init("-"));

  cl::opt<std::string>
  OutputFilename("o", cl::desc("Override output filename"),
                 cl::value_desc("filename"));

  cl::opt<int>
  RunNPasses("stopAfterNPasses",
             cl::desc("Only run the first N passes of gccas"), cl::Hidden,
             cl::value_desc("# passes"));

  cl::opt<bool>
  Verify("verify", cl::desc("Verify each pass result"));
}

static inline void addPass(PassManager &PM, Pass *P) {
  static int NumPassesCreated = 0;

  // If we haven't already created the number of passes that was requested...
  if (RunNPasses == 0 || RunNPasses > NumPassesCreated) {
    // Add the pass to the pass manager...
    PM.add(P);

    // If we are verifying all of the intermediate steps, add the verifier...
    if (Verify) PM.add(createVerifierPass());

    // Keep track of how many passes we made for -stopAfterNPasses
    ++NumPassesCreated;
  } else {
    delete P;             // We don't want this pass to run, just delete it now
  }
}

void AddConfiguredTransformationPasses(PassManager &PM) {
  if (Verify) PM.add(createVerifierPass());

  addPass(PM, createFunctionResolvingPass());    // Resolve (...) functions
  addPass(PM, createGlobalDCEPass());            // Kill unused uinit g-vars
  addPass(PM, createDeadTypeEliminationPass());  // Eliminate dead types
  addPass(PM, createConstantMergePass());        // Merge dup global constants
  addPass(PM, createCFGSimplificationPass());    // Merge & remove BBs
  addPass(PM, createVerifierPass());             // Verify that input is correct
  addPass(PM, createDeadInstEliminationPass());  // Remove Dead code/vars
  addPass(PM, createRaiseAllocationsPass());     // call %malloc -> malloc inst
  addPass(PM, createInstructionCombiningPass()); // Cleanup code for raise
  addPass(PM, createRaisePointerReferencesPass());// Recover type information
  addPass(PM, createInstructionCombiningPass()); // Combine silly seq's
  addPass(PM, createScalarReplAggregatesPass()); // Break up aggregate allocas
  addPass(PM, createPromoteMemoryToRegister());  // Promote alloca's to regs
  addPass(PM, createIndVarSimplifyPass());       // Simplify indvars
  addPass(PM, createReassociatePass());          // Reassociate expressions
  //addPass(PM, createCorrelatedExpressionEliminationPass());// Kill corr branches
  addPass(PM, createInstructionCombiningPass()); // Combine silly seq's
  addPass(PM, createCFGSimplificationPass());    // Merge & remove BBs
  addPass(PM, createLICMPass());                 // Hoist loop invariants
  addPass(PM, createLoadValueNumberingPass());   // GVN for load instructions
  addPass(PM, createGCSEPass());                 // Remove common subexprs
  addPass(PM, createSCCPPass());                 // Constant prop with SCCP

  // Run instcombine after redundancy elimination to exploit opportunities
  // opened up by them.
  addPass(PM, createInstructionCombiningPass());
  addPass(PM, createAggressiveDCEPass());        // SSA based 'Agressive DCE'
  addPass(PM, createCFGSimplificationPass());    // Merge & remove BBs
}

int main(int argc, char **argv) {
  cl::ParseCommandLineOptions(argc, argv, " llvm .s -> .o assembler for GCC\n");

  std::auto_ptr<Module> M;
  try {
    // Parse the file now...
    M.reset(ParseAssemblyFile(InputFilename));
  } catch (const ParseException &E) {
    std::cerr << argv[0] << ": " << E.getMessage() << "\n";
    return 1;
  }

  if (M.get() == 0) {
    std::cerr << argv[0] << ": assembly didn't read correctly.\n";
    return 1;
  }

  std::ostream *Out = 0;
  if (OutputFilename == "") {   // Didn't specify an output filename?
    if (InputFilename == "-") {
      OutputFilename = "-";
    } else {
      std::string IFN = InputFilename;
      int Len = IFN.length();
      if (IFN[Len-2] == '.' && IFN[Len-1] == 's') {   // Source ends in .s?
        OutputFilename = std::string(IFN.begin(), IFN.end()-2);
      } else {
        OutputFilename = IFN;   // Append a .o to it
      }
      OutputFilename += ".o";
    }
  }

  if (OutputFilename == "-")
    Out = &std::cout;
  else {
    Out = new std::ofstream(OutputFilename.c_str(), std::ios::out);

    // Make sure that the Out file gets unlink'd from the disk if we get a
    // signal
    RemoveFileOnSignal(OutputFilename);
  }

  if (!Out->good()) {
    std::cerr << argv[0] << ": error opening " << OutputFilename << "!\n";
    return 1;
  }

  // In addition to just parsing the input from GCC, we also want to spiff it up
  // a little bit.  Do this now.
  //
  PassManager Passes;

  // Add an appropriate TargetData instance for this module...
  Passes.add(new TargetData("gccas", M.get()));

  // Add all of the transformation passes to the pass manager to do the cleanup
  // and optimization of the GCC output.
  //
  AddConfiguredTransformationPasses(Passes);

  // Write bytecode to file...
  Passes.add(new WriteBytecodePass(Out));

  // Run our queue of passes all at once now, efficiently.
  Passes.run(*M.get());

  if (Out != &std::cout) delete Out;
  return 0;
}
<commit_msg>Add tail duplication pass to the pipeline, move the verifier pass to the front Other minor reorganizations<commit_after>//===----------------------------------------------------------------------===//
// LLVM 'GCCAS' UTILITY
//
//  This utility is designed to be used by the GCC frontend for creating
// bytecode files from it's intermediate llvm assembly.  The requirements for
// this utility are thus slightly different than that of the standard as util.
//
//===----------------------------------------------------------------------===//

#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Assembly/Parser.h"
#include "llvm/Transforms/RaisePointerReferences.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Analysis/LoadValueNumbering.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Bytecode/WriteBytecodePass.h"
#include "llvm/Target/TargetData.h"
#include "Support/CommandLine.h"
#include "Support/Signals.h"
#include <memory>
#include <fstream>

namespace {
  cl::opt<std::string>
  InputFilename(cl::Positional,cl::desc("<input llvm assembly>"),cl::init("-"));

  cl::opt<std::string>
  OutputFilename("o", cl::desc("Override output filename"),
                 cl::value_desc("filename"));

  cl::opt<int>
  RunNPasses("stopAfterNPasses",
             cl::desc("Only run the first N passes of gccas"), cl::Hidden,
             cl::value_desc("# passes"));

  cl::opt<bool>
  Verify("verify", cl::desc("Verify each pass result"));
}

static inline void addPass(PassManager &PM, Pass *P) {
  static int NumPassesCreated = 0;

  // If we haven't already created the number of passes that was requested...
  if (RunNPasses == 0 || RunNPasses > NumPassesCreated) {
    // Add the pass to the pass manager...
    PM.add(P);

    // If we are verifying all of the intermediate steps, add the verifier...
    if (Verify) PM.add(createVerifierPass());

    // Keep track of how many passes we made for -stopAfterNPasses
    ++NumPassesCreated;
  } else {
    delete P;             // We don't want this pass to run, just delete it now
  }
}

void AddConfiguredTransformationPasses(PassManager &PM) {
  PM.add(createVerifierPass());                  // Verify that input is correct
  addPass(PM, createFunctionResolvingPass());    // Resolve (...) functions
  addPass(PM, createGlobalDCEPass());            // Kill unused uinit g-vars
  addPass(PM, createDeadTypeEliminationPass());  // Eliminate dead types
  addPass(PM, createConstantMergePass());        // Merge dup global constants
  addPass(PM, createRaiseAllocationsPass());     // call %malloc -> malloc inst
  addPass(PM, createInstructionCombiningPass()); // Cleanup code for raise
  addPass(PM, createRaisePointerReferencesPass());// Recover type information
  addPass(PM, createTailDuplicationPass());      // Simplify cfg by copying code
  addPass(PM, createCFGSimplificationPass());    // Merge & remove BBs
  addPass(PM, createInstructionCombiningPass()); // Combine silly seq's
  addPass(PM, createScalarReplAggregatesPass()); // Break up aggregate allocas
  addPass(PM, createPromoteMemoryToRegister());  // Promote alloca's to regs
  addPass(PM, createIndVarSimplifyPass());       // Simplify indvars
  addPass(PM, createReassociatePass());          // Reassociate expressions
  //addPass(PM, createCorrelatedExpressionEliminationPass());// Kill corr branches
  addPass(PM, createInstructionCombiningPass()); // Combine silly seq's
  addPass(PM, createCFGSimplificationPass());    // Merge & remove BBs
  addPass(PM, createLICMPass());                 // Hoist loop invariants
  addPass(PM, createLoadValueNumberingPass());   // GVN for load instructions
  addPass(PM, createGCSEPass());                 // Remove common subexprs
  addPass(PM, createSCCPPass());                 // Constant prop with SCCP

  // Run instcombine after redundancy elimination to exploit opportunities
  // opened up by them.
  addPass(PM, createInstructionCombiningPass());
  addPass(PM, createAggressiveDCEPass());        // SSA based 'Aggressive DCE'
  addPass(PM, createCFGSimplificationPass());    // Merge & remove BBs
}

int main(int argc, char **argv) {
  cl::ParseCommandLineOptions(argc, argv, " llvm .s -> .o assembler for GCC\n");

  std::auto_ptr<Module> M;
  try {
    // Parse the file now...
    M.reset(ParseAssemblyFile(InputFilename));
  } catch (const ParseException &E) {
    std::cerr << argv[0] << ": " << E.getMessage() << "\n";
    return 1;
  }

  if (M.get() == 0) {
    std::cerr << argv[0] << ": assembly didn't read correctly.\n";
    return 1;
  }

  std::ostream *Out = 0;
  if (OutputFilename == "") {   // Didn't specify an output filename?
    if (InputFilename == "-") {
      OutputFilename = "-";
    } else {
      std::string IFN = InputFilename;
      int Len = IFN.length();
      if (IFN[Len-2] == '.' && IFN[Len-1] == 's') {   // Source ends in .s?
        OutputFilename = std::string(IFN.begin(), IFN.end()-2);
      } else {
        OutputFilename = IFN;   // Append a .o to it
      }
      OutputFilename += ".o";
    }
  }

  if (OutputFilename == "-")
    Out = &std::cout;
  else {
    Out = new std::ofstream(OutputFilename.c_str(), std::ios::out);

    // Make sure that the Out file gets unlink'd from the disk if we get a
    // signal
    RemoveFileOnSignal(OutputFilename);
  }

  if (!Out->good()) {
    std::cerr << argv[0] << ": error opening " << OutputFilename << "!\n";
    return 1;
  }

  // In addition to just parsing the input from GCC, we also want to spiff it up
  // a little bit.  Do this now.
  //
  PassManager Passes;

  // Add an appropriate TargetData instance for this module...
  Passes.add(new TargetData("gccas", M.get()));

  // Add all of the transformation passes to the pass manager to do the cleanup
  // and optimization of the GCC output.
  //
  AddConfiguredTransformationPasses(Passes);

  // Write bytecode to file...
  Passes.add(new WriteBytecodePass(Out));

  // Run our queue of passes all at once now, efficiently.
  Passes.run(*M.get());

  if (Out != &std::cout) delete Out;
  return 0;
}
<|endoftext|>