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

/*!
 * \file
 * \brief EGBLAS wrappers for the bias_add_2d operation.
 */

#pragma once

#ifdef ETL_EGBLAS_MODE

#include "etl/impl/cublas/cuda.hpp"
#include "etl/util/counters.hpp"

#include <egblas.hpp>

#endif

namespace etl {

namespace impl {

namespace egblas {

/*!
 * \brief Indicates if EGBLAS has single-precision absarithm.
 */
#ifdef EGBLAS_HAS_SBIAS_ADD_2D
static constexpr bool has_sbias_add_2d = true;
#else
static constexpr bool has_sbias_add_2d = false;
#endif

/*!
 * \brief Add the 1D bias to to the batched 1D input
 * \param m The first dimension of x and y
 * \param n The second dimension of x and y
 * \param x The vector x (GPU memory)
 * \param incx The stride of x
 * \param b The vector x (GPU memory)
 * \param incb The stride of x
 * \param y The vector y (GPU memory)
 * \param incy The stride of y
 */
void bias_add_2d(size_t m, size_t n, const float* x, size_t incx, const float* b, size_t incb, float* y, size_t incy){
#ifdef EGBLAS_HAS_SBIAS_ADD_2D
    inc_counter("egblas");
    egblas_sbias_add_2d(m, n, x, incx, b, incb, y, incy);
#else
    cpp_unused(m);
    cpp_unused(n);
    cpp_unused(x);
    cpp_unused(incx);
    cpp_unused(b);
    cpp_unused(incb);
    cpp_unused(y);
    cpp_unused(incy);

    cpp_unreachable("Invalid call to egblas::bias_add_2d");
#endif
}

/*!
 * \brief Indicates if EGBLAS has double-precision absarithm.
 */
#ifdef EGBLAS_HAS_DBIAS_ADD_2D
static constexpr bool has_dbias_add_2d = true;
#else
static constexpr bool has_dbias_add_2d = false;
#endif

/*!
 * \brief Add the 1D bias to to the batched 1D input
 * \param m The first dimension of x and y
 * \param n The second dimension of x and y
 * \param x The vector x (GPU memory)
 * \param incx The stride of x
 * \param b The vector x (GPU memory)
 * \param incb The stride of x
 * \param y The vector y (GPU memory)
 * \param incy The stride of y
 */
void bias_add_2d(size_t m, size_t n, const double* x, size_t incx, const double* b, size_t incb, double* y, size_t incy){
#ifdef EGBLAS_HAS_DBIAS_ADD_2D
    inc_counter("egblas");
    egblas_dbias_add_2d(m, n, x, incx, b, incb, y, incy);
#else
    cpp_unused(m);
    cpp_unused(n);
    cpp_unused(x);
    cpp_unused(incx);
    cpp_unused(b);
    cpp_unused(incb);
    cpp_unused(y);
    cpp_unused(incy);

    cpp_unreachable("Invalid call to egblas::bias_add_2d");
#endif
}

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

/*!
 * \file
 * \brief EGBLAS wrappers for the bias_add_2d operation.
 */

#pragma once

#ifdef ETL_EGBLAS_MODE

#include "etl/impl/cublas/cuda.hpp"
#include "etl/util/counters.hpp"

#include <egblas.hpp>

#endif

namespace etl {

namespace impl {

namespace egblas {

/*!
 * \brief Indicates if EGBLAS has single-precision absarithm.
 */
#ifdef EGBLAS_HAS_SBIAS_ADD_2D
static constexpr bool has_sbias_add_2d = true;
#else
static constexpr bool has_sbias_add_2d = false;
#endif

/*!
 * \brief Add the 1D bias to to the batched 1D input
 * \param m The first dimension of x and y
 * \param n The second dimension of x and y
 * \param x The vector x (GPU memory)
 * \param incx The stride of x
 * \param b The vector x (GPU memory)
 * \param incb The stride of x
 * \param y The vector y (GPU memory)
 * \param incy The stride of y
 */
inline void bias_add_2d(size_t m, size_t n, const float* x, size_t incx, const float* b, size_t incb, float* y, size_t incy){
#ifdef EGBLAS_HAS_SBIAS_ADD_2D
    inc_counter("egblas");
    egblas_sbias_add_2d(m, n, x, incx, b, incb, y, incy);
#else
    cpp_unused(m);
    cpp_unused(n);
    cpp_unused(x);
    cpp_unused(incx);
    cpp_unused(b);
    cpp_unused(incb);
    cpp_unused(y);
    cpp_unused(incy);

    cpp_unreachable("Invalid call to egblas::bias_add_2d");
#endif
}

/*!
 * \brief Indicates if EGBLAS has double-precision absarithm.
 */
#ifdef EGBLAS_HAS_DBIAS_ADD_2D
static constexpr bool has_dbias_add_2d = true;
#else
static constexpr bool has_dbias_add_2d = false;
#endif

/*!
 * \brief Add the 1D bias to to the batched 1D input
 * \param m The first dimension of x and y
 * \param n The second dimension of x and y
 * \param x The vector x (GPU memory)
 * \param incx The stride of x
 * \param b The vector x (GPU memory)
 * \param incb The stride of x
 * \param y The vector y (GPU memory)
 * \param incy The stride of y
 */
inline void bias_add_2d(size_t m, size_t n, const double* x, size_t incx, const double* b, size_t incb, double* y, size_t incy){
#ifdef EGBLAS_HAS_DBIAS_ADD_2D
    inc_counter("egblas");
    egblas_dbias_add_2d(m, n, x, incx, b, incb, y, incy);
#else
    cpp_unused(m);
    cpp_unused(n);
    cpp_unused(x);
    cpp_unused(incx);
    cpp_unused(b);
    cpp_unused(incb);
    cpp_unused(y);
    cpp_unused(incy);

    cpp_unreachable("Invalid call to egblas::bias_add_2d");
#endif
}

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


<commit_before>/** \file jsonv/detail/string_view.hpp
 *  The JsonVoorhees implementation of string_view. You should not include this directly; instead, prefer including
 *  \c jsonv/string_view.hpp and manipulating \c JSONV_STRING_REF_TYPE and \c JSONV_STRING_REF_INCLUDE.
 *
 *  Copyright (c) 2014 by Travis Gockel. All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify it under the terms of the Apache License
 *  as published by the Apache Software Foundation, either version 2 of the License, or (at your option) any later
 *  version.
 *
 *  \author Travis Gockel (travis@gockelhut.com)
**/
#ifndef __JSONV_DETAIL_STRING_VIEW_HPP_INCLUDED__
#define __JSONV_DETAIL_STRING_VIEW_HPP_INCLUDED__

#include <jsonv/config.hpp>

#include <algorithm>
#include <cstddef>
#include <cstring>
#include <iterator>
#include <ostream>
#include <stdexcept>

namespace jsonv
{
namespace detail
{

/** A non-owning reference to an \c std::string, as proposed to the C++ Standard Committee by Jeffrey Yasskin in N3921
 *  (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3921.html). Unlike the one proposed, this is not templated
 *  over the \c char type, as this project only deals with UTF-8 encoded strings.
**/
class string_view
{
public:
    using value_type             = char;
    using pointer                = const value_type*;
    using reference              = const value_type&;
    using const_reference        = const value_type&;
    using iterator               = pointer;
    using const_iterator         = pointer;
    using reverse_iterator       = std::reverse_iterator<iterator>;
    using const_reverse_iterator = std::reverse_iterator<const_iterator>;
    using size_type              = std::size_t;
    using difference_type        = std::ptrdiff_t;

    static constexpr size_type npos = size_type(~0);

public:
    constexpr string_view() noexcept :
            _base(nullptr),
            _length(0)
    { }

    string_view(pointer p) noexcept :
            _base(p),
            _length(std::strlen(p))
    { }

    constexpr string_view(pointer p, size_type len) noexcept :
            _base(p),
            _length(len)
    { }

    template <typename UAllocator>
    string_view(const std::basic_string<value_type, std::char_traits<value_type>, UAllocator>& src)
                noexcept(noexcept(src.data()) && noexcept(src.length())):
            _base(src.data()),
            _length(src.length())
    { }

    string_view(const string_view&) noexcept = default;
    string_view& operator=(const string_view&) noexcept = default;

    template <typename UAllocator>
    explicit operator std::basic_string<value_type, std::char_traits<value_type>, UAllocator>() const
    {
        return std::basic_string<value_type, std::char_traits<value_type>, UAllocator>(_base, _length);
    }

    #ifdef _MSC_VER
    // MSVC 14 CTP 5 has issues picking up templated cast operators, so provide this one for the sake of convenience
    explicit operator std::string() const
    {
        return std::string(_base, _length);
    }
    #endif

    constexpr size_type size()     const noexcept { return _length; }
    constexpr size_type max_size() const noexcept { return _length; }
    constexpr size_type length()   const noexcept { return _length; }

    constexpr bool empty() const noexcept { return _length == 0; }

    constexpr const_reference operator[](size_type idx) const { return _base[idx]; }
    const_reference at(size_type idx) const
    {
        if (idx < _length)
            return _base[idx];
        else
            throw std::out_of_range("jsonv::string_view::at");
    }

    constexpr const_reference front() const { return _base[0]; }
    constexpr const_reference back()  const { return _base[_length - 1]; }

    constexpr pointer data() const { return _base; }

    constexpr const_iterator begin()  const { return _base; }
    constexpr const_iterator cbegin() const { return _base; }
    constexpr const_iterator end()    const { return _base + _length; }
    constexpr const_iterator cend()   const { return _base + _length; }

    const_reverse_iterator rbegin()  const { return const_reverse_iterator(end()); }
    const_reverse_iterator crbegin() const { return const_reverse_iterator(end()); }
    const_reverse_iterator rend()    const { return const_reverse_iterator(begin()); }
    const_reverse_iterator crend()   const { return const_reverse_iterator(begin()); }

    void clear()
    {
        _base = nullptr;
        _length = 0;
    }

    void remove_prefix(size_type n)
    {
        if (n <= _length)
        {
            _base += n;
            _length -= n;
        }
        else
        {
            throw std::range_error("jsonv::string_view::remove_prefix");
        }
    }

    void remove_suffix(size_type n)
    {
        if (n <= _length)
        {
            _length -= n;
        }
        else
        {
            throw std::range_error("jsonv::string_view::remove_prefix");
        }
    }

    string_view substr(size_type idx, size_type count = npos) const
    {
        count = count == npos ? (_length - idx) : count;
        if (idx + count <= _length)
            return string_view(_base + idx, count);
        else
            throw std::range_error("jsonv::string_view::substr");
    }

    bool starts_with(value_type val) const
    {
        return !empty() && front() == val;
    }

    bool starts_with(const string_view& sub) const
    {
        return sub.length() <= length() && std::equal(sub.begin(), sub.end(), begin());
    }

    bool ends_with(value_type val) const
    {
        return !empty() && back() == val;
    }

    bool ends_with(const string_view& sub) const
    {
        return sub.length() <= length() && std::equal(sub.rbegin(), sub.rend(), rbegin());
    }

    size_type find(const string_view& sub) const
    {
        auto iter = std::search(begin(), end(), sub.begin(), sub.end());
        return iter == end() ? npos : std::distance(begin(), iter);
    }

    size_type find(value_type val) const
    {
        auto iter = std::find(begin(), end(), val);
        return iter == end() ? npos : std::distance(begin(), iter);
    }

    size_type rfind(const string_view& sub) const
    {
        auto iter = std::search(rbegin(), rend(), sub.rbegin(), sub.rend());
        return iter == rend() ? npos : std::distance(iter, rend());
    }

    size_type rfind(value_type val) const
    {
        auto iter = std::find(rbegin(), rend(), val);
        return iter == rend() ? npos : std::distance(iter, rend());
    }

    size_type find_first_of(value_type val) const
    {
        return find(val);
    }

    size_type find_first_of(const string_view& chars) const
    {
        auto iter = std::find_first_of(begin(), end(), chars.begin(), chars.end());
        return iter == end() ? npos : std::distance(begin(), iter);
    }

    size_type find_first_not_of(value_type val) const
    {
        auto iter = std::find_if(begin(), end(), [val] (value_type x) { return val != x; });
        return iter == end() ? npos : std::distance(begin(), iter);
    }

    size_type find_first_not_of(const string_view& chars) const
    {
        auto iter = std::find_if(begin(), end(),
                                 [&chars] (value_type x)
                                 {
                                     return chars.find(x) == npos;
                                 }
                                );
        return iter == end() ? npos : std::distance(begin(), iter);
    }

    size_type find_last_of(value_type val) const
    {
        return rfind(val);
    }

    size_type find_last_of(const string_view& chars) const
    {
        auto iter = std::find_first_of(rbegin(), rend(), chars.begin(), chars.end());
        return iter == rend() ? npos : std::distance(iter, rend());
    }

    size_type find_last_not_of(value_type val) const
    {
        auto iter = std::find_if(rbegin(), rend(), [val] (value_type x) { return val != x; });
        return iter == rend() ? npos : std::distance(iter, rend());
    }

    size_type find_last_not_of(const string_view& chars) const
    {
        auto iter = std::find_if(rbegin(), rend(),
                                 [&chars] (value_type x)
                                 {
                                     return chars.find(x) == npos;
                                 }
                                );
        return iter == rend() ? npos : std::distance(iter, rend());
    }

    bool operator==(const string_view& other) const
    {
        return _length == other._length
            && (_base == other._base || std::equal(begin(), end(), other.begin()));
    }

    bool operator!=(const string_view& other) const
    {
        return !operator==(other);
    }

    bool operator<(const string_view& other) const
    {
        return std::lexicographical_compare(begin(), end(), other.begin(), other.end());
    }

    bool operator<=(const string_view& other) const
    {
        return !(other < *this);
    }

    bool operator>(const string_view& other) const
    {
        return other < *this;
    }

    bool operator>=(const string_view& other) const
    {
        return !(*this < other);
    }

    friend std::ostream& operator<<(std::ostream& os, const string_view& self)
    {
        os.write(self.begin(), self.size());
        return os;
    }

private:
    pointer   _base;
    size_type _length;
};

}
}

#endif/*__JSONV_DETAIL_STRING_VIEW_HPP_INCLUDED__*/
<commit_msg>Adds free functions for comparisons between std::string and detail::string_view.<commit_after>/** \file jsonv/detail/string_view.hpp
 *  The JsonVoorhees implementation of string_view. You should not include this directly; instead, prefer including
 *  \c jsonv/string_view.hpp and manipulating \c JSONV_STRING_REF_TYPE and \c JSONV_STRING_REF_INCLUDE.
 *
 *  Copyright (c) 2014 by Travis Gockel. All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify it under the terms of the Apache License
 *  as published by the Apache Software Foundation, either version 2 of the License, or (at your option) any later
 *  version.
 *
 *  \author Travis Gockel (travis@gockelhut.com)
**/
#ifndef __JSONV_DETAIL_STRING_VIEW_HPP_INCLUDED__
#define __JSONV_DETAIL_STRING_VIEW_HPP_INCLUDED__

#include <jsonv/config.hpp>

#include <algorithm>
#include <cstddef>
#include <cstring>
#include <iterator>
#include <ostream>
#include <stdexcept>

namespace jsonv
{
namespace detail
{

/** A non-owning reference to an \c std::string, as proposed to the C++ Standard Committee by Jeffrey Yasskin in N3921
 *  (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3921.html). Unlike the one proposed, this is not templated
 *  over the \c char type, as this project only deals with UTF-8 encoded strings.
**/
class string_view
{
public:
    using value_type             = char;
    using pointer                = const value_type*;
    using reference              = const value_type&;
    using const_reference        = const value_type&;
    using iterator               = pointer;
    using const_iterator         = pointer;
    using reverse_iterator       = std::reverse_iterator<iterator>;
    using const_reverse_iterator = std::reverse_iterator<const_iterator>;
    using size_type              = std::size_t;
    using difference_type        = std::ptrdiff_t;

    static constexpr size_type npos = size_type(~0);

public:
    constexpr string_view() noexcept :
            _base(nullptr),
            _length(0)
    { }

    string_view(pointer p) noexcept :
            _base(p),
            _length(std::strlen(p))
    { }

    constexpr string_view(pointer p, size_type len) noexcept :
            _base(p),
            _length(len)
    { }

    template <typename UAllocator>
    string_view(const std::basic_string<value_type, std::char_traits<value_type>, UAllocator>& src)
                noexcept(noexcept(src.data()) && noexcept(src.length())):
            _base(src.data()),
            _length(src.length())
    { }

    string_view(const string_view&) noexcept = default;
    string_view& operator=(const string_view&) noexcept = default;

    template <typename UAllocator>
    explicit operator std::basic_string<value_type, std::char_traits<value_type>, UAllocator>() const
    {
        return std::basic_string<value_type, std::char_traits<value_type>, UAllocator>(_base, _length);
    }

    #ifdef _MSC_VER
    // MSVC 14 CTP 5 has issues picking up templated cast operators, so provide this one for the sake of convenience
    explicit operator std::string() const
    {
        return std::string(_base, _length);
    }
    #endif

    constexpr size_type size()     const noexcept { return _length; }
    constexpr size_type max_size() const noexcept { return _length; }
    constexpr size_type length()   const noexcept { return _length; }

    constexpr bool empty() const noexcept { return _length == 0; }

    constexpr const_reference operator[](size_type idx) const { return _base[idx]; }
    const_reference at(size_type idx) const
    {
        if (idx < _length)
            return _base[idx];
        else
            throw std::out_of_range("jsonv::string_view::at");
    }

    constexpr const_reference front() const { return _base[0]; }
    constexpr const_reference back()  const { return _base[_length - 1]; }

    constexpr pointer data() const { return _base; }

    constexpr const_iterator begin()  const { return _base; }
    constexpr const_iterator cbegin() const { return _base; }
    constexpr const_iterator end()    const { return _base + _length; }
    constexpr const_iterator cend()   const { return _base + _length; }

    const_reverse_iterator rbegin()  const { return const_reverse_iterator(end()); }
    const_reverse_iterator crbegin() const { return const_reverse_iterator(end()); }
    const_reverse_iterator rend()    const { return const_reverse_iterator(begin()); }
    const_reverse_iterator crend()   const { return const_reverse_iterator(begin()); }

    void clear()
    {
        _base = nullptr;
        _length = 0;
    }

    void remove_prefix(size_type n)
    {
        if (n <= _length)
        {
            _base += n;
            _length -= n;
        }
        else
        {
            throw std::range_error("jsonv::string_view::remove_prefix");
        }
    }

    void remove_suffix(size_type n)
    {
        if (n <= _length)
        {
            _length -= n;
        }
        else
        {
            throw std::range_error("jsonv::string_view::remove_prefix");
        }
    }

    string_view substr(size_type idx, size_type count = npos) const
    {
        count = count == npos ? (_length - idx) : count;
        if (idx + count <= _length)
            return string_view(_base + idx, count);
        else
            throw std::range_error("jsonv::string_view::substr");
    }

    bool starts_with(value_type val) const
    {
        return !empty() && front() == val;
    }

    bool starts_with(const string_view& sub) const
    {
        return sub.length() <= length() && std::equal(sub.begin(), sub.end(), begin());
    }

    bool ends_with(value_type val) const
    {
        return !empty() && back() == val;
    }

    bool ends_with(const string_view& sub) const
    {
        return sub.length() <= length() && std::equal(sub.rbegin(), sub.rend(), rbegin());
    }

    size_type find(const string_view& sub) const
    {
        auto iter = std::search(begin(), end(), sub.begin(), sub.end());
        return iter == end() ? npos : std::distance(begin(), iter);
    }

    size_type find(value_type val) const
    {
        auto iter = std::find(begin(), end(), val);
        return iter == end() ? npos : std::distance(begin(), iter);
    }

    size_type rfind(const string_view& sub) const
    {
        auto iter = std::search(rbegin(), rend(), sub.rbegin(), sub.rend());
        return iter == rend() ? npos : std::distance(iter, rend());
    }

    size_type rfind(value_type val) const
    {
        auto iter = std::find(rbegin(), rend(), val);
        return iter == rend() ? npos : std::distance(iter, rend());
    }

    size_type find_first_of(value_type val) const
    {
        return find(val);
    }

    size_type find_first_of(const string_view& chars) const
    {
        auto iter = std::find_first_of(begin(), end(), chars.begin(), chars.end());
        return iter == end() ? npos : std::distance(begin(), iter);
    }

    size_type find_first_not_of(value_type val) const
    {
        auto iter = std::find_if(begin(), end(), [val] (value_type x) { return val != x; });
        return iter == end() ? npos : std::distance(begin(), iter);
    }

    size_type find_first_not_of(const string_view& chars) const
    {
        auto iter = std::find_if(begin(), end(),
                                 [&chars] (value_type x)
                                 {
                                     return chars.find(x) == npos;
                                 }
                                );
        return iter == end() ? npos : std::distance(begin(), iter);
    }

    size_type find_last_of(value_type val) const
    {
        return rfind(val);
    }

    size_type find_last_of(const string_view& chars) const
    {
        auto iter = std::find_first_of(rbegin(), rend(), chars.begin(), chars.end());
        return iter == rend() ? npos : std::distance(iter, rend());
    }

    size_type find_last_not_of(value_type val) const
    {
        auto iter = std::find_if(rbegin(), rend(), [val] (value_type x) { return val != x; });
        return iter == rend() ? npos : std::distance(iter, rend());
    }

    size_type find_last_not_of(const string_view& chars) const
    {
        auto iter = std::find_if(rbegin(), rend(),
                                 [&chars] (value_type x)
                                 {
                                     return chars.find(x) == npos;
                                 }
                                );
        return iter == rend() ? npos : std::distance(iter, rend());
    }

    bool operator==(const string_view& other) const
    {
        return _length == other._length
            && (_base == other._base || std::equal(begin(), end(), other.begin()));
    }

    bool operator!=(const string_view& other) const
    {
        return !operator==(other);
    }

    bool operator<(const string_view& other) const
    {
        return std::lexicographical_compare(begin(), end(), other.begin(), other.end());
    }

    bool operator<=(const string_view& other) const
    {
        return !(other < *this);
    }

    bool operator>(const string_view& other) const
    {
        return other < *this;
    }

    bool operator>=(const string_view& other) const
    {
        return !(*this < other);
    }

    friend std::ostream& operator<<(std::ostream& os, const string_view& self)
    {
        os.write(self.begin(), self.size());
        return os;
    }

private:
    pointer   _base;
    size_type _length;
};

template <typename UAllocator>
bool operator==(const std::basic_string<UAllocator> lhs, const string_view& rhs)
{
    return string_view(lhs) == rhs;
}

template <typename UAllocator>
bool operator!=(const std::basic_string<UAllocator> lhs, const string_view& rhs)
{
    return string_view(lhs) != rhs;
}

template <typename UAllocator>
bool operator<(const std::basic_string<UAllocator> lhs, const string_view& rhs)
{
    return string_view(lhs) < rhs;
}

template <typename UAllocator>
bool operator<=(const std::basic_string<UAllocator> lhs, const string_view& rhs)
{
    return string_view(lhs) <= rhs;
}

template <typename UAllocator>
bool operator>(const std::basic_string<UAllocator> lhs, const string_view& rhs)
{
    return string_view(lhs) > rhs;
}

template <typename UAllocator>
bool operator>=(const std::basic_string<UAllocator> lhs, const string_view& rhs)
{
    return string_view(lhs) >= rhs;
}

}
}

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


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#ifndef MTAC_GLOBAL_OPTIMIZATIONS_H
#define MTAC_GLOBAL_OPTIMIZATIONS_H

#include <memory>
#include <iostream>

#include "assert.hpp"
#include "logging.hpp"

#include "mtac/Program.hpp"
#include "mtac/DataFlowProblem.hpp"

namespace eddic {

namespace mtac {

template<DataFlowType Type, typename DomainValues>
std::shared_ptr<DataFlowResults<mtac::Domain<DomainValues>>> data_flow(std::shared_ptr<mtac::Function> function, DataFlowProblem<Type, DomainValues>& problem){
    if(Type == DataFlowType::Forward){
        return forward_data_flow(function, problem);
    } else if(Type == DataFlowType::Backward){
        return backward_data_flow(function, problem);
    } else {
        ASSERT_PATH_NOT_TAKEN("This data-flow type is not handled");
    }
}

template<typename Left, typename Right>
inline void assign(Left& old, Right&& value, bool& changes){
    if(old.top()){
        changes = !value.top();
    } else if(old.values().size() != value.values().size()){
        changes = true;
    }

    old = value;
}

template<DataFlowType Type, typename DomainValues>
std::shared_ptr<DataFlowResults<mtac::Domain<DomainValues>>> forward_data_flow(std::shared_ptr<mtac::Function> function, DataFlowProblem<Type, DomainValues>& problem){
    typedef mtac::Domain<DomainValues> Domain;

    auto results = std::make_shared<DataFlowResults<Domain>>();

    auto& OUT = results->OUT;
    auto& IN = results->IN;

    auto& OUT_S = results->OUT_S;
    auto& IN_S = results->IN_S;

    OUT[function->entry_bb()] = problem.Boundary(function);
    log::emit<Dev>("Data-Flow") << "OUT[" << *function->entry_bb() << "] set to " << OUT[function->entry_bb()] << log::endl;

    for(auto& block : function){
        //Initialize all but ENTRY
        if(block->index != -1){
            OUT[block] = problem.Init(function);
            log::emit<Dev>("Data-Flow") << "OUT[" << *block << "] set to " << OUT[block] << log::endl;
        }
    }

    bool changes = true;
    while(changes){
        changes = false;

        for(auto& B : function){
            //Do not consider ENTRY
            if(B->index == -1){
                continue;
            }

            for(auto& P : B->predecessors){
                log::emit<Dev>("Data-Flow") << "Meet B = " << *B << " with P = " << *P << log::endl;
                log::emit<Dev>("Data-Flow") << "IN[B] before " << IN[B] << log::endl;
                log::emit<Dev>("Data-Flow") << "OUT[P] before " << OUT[P] << log::endl;

                IN[B] = problem.meet(IN[B], OUT[P]);

                log::emit<Dev>("Data-Flow") << "IN[B] after " << IN[B] << log::endl;

                auto& statements = B->statements;

                if(statements.size() > 0){
                    IN_S[statements.front()] = IN[B];

                    for(unsigned i = 0; i < statements.size(); ++i){
                        auto& statement = statements[i];

                        assign(OUT_S[statement], problem.transfer(B, statement, IN_S[statement]), changes);

                        //The entry value of the next statement are the exit values of the current statement
                        if(i != statements.size() - 1){
                            IN_S[statements[i+1]] = OUT_S[statement];
                        }
                    }

                    assign(OUT[B], OUT_S[statements.back()], changes);
                } else {
                    //If the basic block is empty, the OUT values are the IN values
                    assign(OUT[B], IN[B], changes);
                }
            }
        }
    }

    return results;
}

template<DataFlowType Type, typename DomainValues>
std::shared_ptr<DataFlowResults<mtac::Domain<DomainValues>>> backward_data_flow(std::shared_ptr<mtac::Function> function, DataFlowProblem<Type, DomainValues>& problem){
    typedef mtac::Domain<DomainValues> Domain;

    auto results = std::make_shared<DataFlowResults<Domain>>();

    auto& OUT = results->OUT;
    auto& IN = results->IN;

    auto& OUT_S = results->OUT_S;
    auto& IN_S = results->IN_S;

    IN[function->exit_bb()] = problem.Boundary(function);
    log::emit<Dev>("Data-Flow") << "IN[" << *function->exit_bb() << "] set to " << IN[function->exit_bb()] << log::endl;

    for(auto& block : function){
        //Init all but EXIT
        if(block->index != -2){
            IN[block] = problem.Init(function);
            log::emit<Dev>("Data-Flow") << "IN[" << *block << "] set to " << IN[block] << log::endl;
        }
    }

    bool changes = true;
    while(changes){
        changes = false;

        for(auto& B : function){
            //Do not consider EXIT
            if(B->index == -2){
                continue;
            }

            for(auto& S : B->successors){
                log::emit<Dev>("Data-Flow") << "Meet B = " << *B << " with S = " << *S << log::endl;
                log::emit<Dev>("Data-Flow") << "OUT[B] before " << OUT[B] << log::endl;
                log::emit<Dev>("Data-Flow") << "IN[S] before " << IN[S] << log::endl;

                OUT[B] = problem.meet(OUT[B], IN[S]);

                log::emit<Dev>("Data-Flow") << "OUT[B] after " << OUT[B] << log::endl;

                auto& statements = B->statements;

                if(statements.size() > 0){
                    assign(OUT_S[statements.back()], OUT[B], changes);

                    for(unsigned i = statements.size() - 1; i > 0; --i){
                        auto& statement = statements[i];

                        log::emit<Dev>("Data-Flow") << "IN_S[" << i << "] before transfer " << IN_S[statement] << log::endl;
                        assign(IN_S[statement], problem.transfer(B, statement, OUT_S[statement]), changes);
                        log::emit<Dev>("Data-Flow") << "IN_S[" << i << "] after transfer " << IN_S[statement] << log::endl;

                        OUT_S[statements[i-1]] = IN_S[statement];
                    }

                    assign(IN_S[statements[0]], problem.transfer(B, statements[0], OUT_S[statements[0]]), changes);

                    assign(IN[B], IN_S[statements.front()], changes);
                } else {
                    //If the basic block is empty, the IN values are the OUT values
                    assign(IN[B], OUT[B], changes);
                }

                log::emit<Dev>("Data-Flow") << "IN[B] after transfer " << IN[B] << log::endl;
            }
        }
    }

    return results;
}

} //end of mtac

} //end of eddic

#endif
<commit_msg>Better logging<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#ifndef MTAC_GLOBAL_OPTIMIZATIONS_H
#define MTAC_GLOBAL_OPTIMIZATIONS_H

#include <memory>
#include <iostream>

#include "assert.hpp"
#include "logging.hpp"

#include "mtac/Program.hpp"
#include "mtac/DataFlowProblem.hpp"

namespace eddic {

namespace mtac {

template<DataFlowType Type, typename DomainValues>
std::shared_ptr<DataFlowResults<mtac::Domain<DomainValues>>> data_flow(std::shared_ptr<mtac::Function> function, DataFlowProblem<Type, DomainValues>& problem){
    if(Type == DataFlowType::Forward){
        return forward_data_flow(function, problem);
    } else if(Type == DataFlowType::Backward){
        return backward_data_flow(function, problem);
    } else {
        ASSERT_PATH_NOT_TAKEN("This data-flow type is not handled");
    }
}

template<typename Left, typename Right>
inline void assign(Left& old, Right&& value, bool& changes){
    if(old.top()){
        changes = !value.top();
    } else if(old.values().size() != value.values().size()){
        changes = true;
    }

    old = value;
}

template<DataFlowType Type, typename DomainValues>
std::shared_ptr<DataFlowResults<mtac::Domain<DomainValues>>> forward_data_flow(std::shared_ptr<mtac::Function> function, DataFlowProblem<Type, DomainValues>& problem){
    typedef mtac::Domain<DomainValues> Domain;

    auto results = std::make_shared<DataFlowResults<Domain>>();

    auto& OUT = results->OUT;
    auto& IN = results->IN;

    auto& OUT_S = results->OUT_S;
    auto& IN_S = results->IN_S;

    OUT[function->entry_bb()] = problem.Boundary(function);
    log::emit<Dev>("Data-Flow") << "OUT[" << *function->entry_bb() << "] set to " << OUT[function->entry_bb()] << log::endl;

    for(auto& block : function){
        //Initialize all but ENTRY
        if(block->index != -1){
            OUT[block] = problem.Init(function);
            log::emit<Dev>("Data-Flow") << "OUT[" << *block << "] set to " << OUT[block] << log::endl;
        }
    }

    bool changes = true;
    while(changes){
        changes = false;

        for(auto& B : function){
            //Do not consider ENTRY
            if(B->index == -1){
                continue;
            }

            for(auto& P : B->predecessors){
                log::emit<Dev>("Data-Flow") << "Meet B = " << *B << " with P = " << *P << log::endl;
                log::emit<Dev>("Data-Flow") << "IN[B] before " << IN[B] << log::endl;
                log::emit<Dev>("Data-Flow") << "OUT[P] before " << OUT[P] << log::endl;

                IN[B] = problem.meet(IN[B], OUT[P]);

                log::emit<Dev>("Data-Flow") << "IN[B] after " << IN[B] << log::endl;

                auto& statements = B->statements;

                if(statements.size() > 0){
                    IN_S[statements.front()] = IN[B];

                    for(unsigned i = 0; i < statements.size(); ++i){
                        auto& statement = statements[i];

                        assign(OUT_S[statement], problem.transfer(B, statement, IN_S[statement]), changes);

                        //The entry value of the next statement are the exit values of the current statement
                        if(i != statements.size() - 1){
                            IN_S[statements[i+1]] = OUT_S[statement];
                        }
                    }

                    assign(OUT[B], OUT_S[statements.back()], changes);
                } else {
                    //If the basic block is empty, the OUT values are the IN values
                    assign(OUT[B], IN[B], changes);
                }
            }
        }
    }

    return results;
}

template<DataFlowType Type, typename DomainValues>
std::shared_ptr<DataFlowResults<mtac::Domain<DomainValues>>> backward_data_flow(std::shared_ptr<mtac::Function> function, DataFlowProblem<Type, DomainValues>& problem){
    typedef mtac::Domain<DomainValues> Domain;

    auto results = std::make_shared<DataFlowResults<Domain>>();

    auto& OUT = results->OUT;
    auto& IN = results->IN;

    auto& OUT_S = results->OUT_S;
    auto& IN_S = results->IN_S;

    IN[function->exit_bb()] = problem.Boundary(function);
    log::emit<Dev>("Data-Flow") << "IN[" << *function->exit_bb() << "] set to " << IN[function->exit_bb()] << log::endl;

    for(auto& block : function){
        //Init all but EXIT
        if(block->index != -2){
            IN[block] = problem.Init(function);
            log::emit<Dev>("Data-Flow") << "IN[" << *block << "] set to " << IN[block] << log::endl;
        }
    }

    bool changes = true;
    while(changes){
        changes = false;

        for(auto& B : function){
            //Do not consider EXIT
            if(B->index == -2){
                continue;
            }

            for(auto& S : B->successors){
                log::emit<Dev>("Data-Flow") << "Meet B = " << *B << " with S = " << *S << log::endl;
                log::emit<Dev>("Data-Flow") << "OUT[B] before " << OUT[B] << log::endl;
                log::emit<Dev>("Data-Flow") << "IN[S] before " << IN[S] << log::endl;

                OUT[B] = problem.meet(OUT[B], IN[S]);

                log::emit<Dev>("Data-Flow") << "OUT[B] after " << OUT[B] << log::endl;

                auto& statements = B->statements;

                if(statements.size() > 0){
                    log::emit<Dev>("Data-Flow") << "OUT_S[" << (statements.size() - 1) << "] before transfer " << OUT_S[statements[statements.size() - 1]] << log::endl;
                    assign(OUT_S[statements.back()], OUT[B], changes);
                    log::emit<Dev>("Data-Flow") << "OUT_S[" << (statements.size() - 1) << "] after transfer " << OUT_S[statements[statements.size() - 1]] << log::endl;

                    for(unsigned i = statements.size() - 1; i > 0; --i){
                        auto& statement = statements[i];

                        log::emit<Dev>("Data-Flow") << "IN_S[" << i << "] before transfer " << IN_S[statement] << log::endl;
                        assign(IN_S[statement], problem.transfer(B, statement, OUT_S[statement]), changes);
                        log::emit<Dev>("Data-Flow") << "IN_S[" << i << "] after transfer " << IN_S[statement] << log::endl;

                        log::emit<Dev>("Data-Flow") << "OUT_S[" << (i - 1) << "] before transfer " << OUT_S[statements[i - 1]] << log::endl;
                        OUT_S[statements[i-1]] = IN_S[statement];
                        log::emit<Dev>("Data-Flow") << "OUT_S[" << (i - 1) << "] after transfer " << OUT_S[statements[i - 1]] << log::endl;
                    }

                    log::emit<Dev>("Data-Flow") << "IN_S[" << 0 << "] before transfer " << IN_S[statements[0]] << log::endl;
                    assign(IN_S[statements[0]], problem.transfer(B, statements[0], OUT_S[statements[0]]), changes);
                    log::emit<Dev>("Data-Flow") << "IN_S[" << 0 << "] after transfer " << IN_S[statements[0]] << log::endl;

                    assign(IN[B], IN_S[statements.front()], changes);
                } else {
                    //If the basic block is empty, the IN values are the OUT values
                    assign(IN[B], OUT[B], changes);
                }

                log::emit<Dev>("Data-Flow") << "IN[B] after transfer " << IN[B] << log::endl;
            }
        }
    }

    return results;
}

} //end of mtac

} //end of eddic

#endif
<|endoftext|>


<commit_before>// ============================================================================
//                 SeqAn - The Library for Sequence Analysis
// ============================================================================
//
// Copyright (c) 2006-2017, Knut Reinert & Freie Universitaet Berlin
// Copyright (c) 2016-2017, Knut Reinert & MPI Molekulare Genetik
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of Knut Reinert or the FU Berlin nor the names of
//       its contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
// DAMAGE.
//
// ============================================================================

/*!\file core/concept/core.hpp
 * \brief Adaptions of core concepts from the Ranges TS.
 * \ingroup core
 * \author Rene Rahn <rene.rahn AT fu-berlin.de>
 */

#pragma once

#include <range/v3/range_concepts.hpp>
#include <range/v3/utility/functional.hpp>

namespace seqan3
{

//!\name Core Language Concepts
//!\{
/*!\brief Resolves to `ranges::Same<types...>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/Same
 */
template <typename ...ts>
concept bool same_concept =                         static_cast<bool>(ranges::Same<ts...>());

/*!\brief Resolves to `ranges::DerivedFrom<type1, type2>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/DerivedFrom
 */
template <typename t, typename u>
concept bool derived_from_conept =                  static_cast<bool>(ranges::DerivedFrom<t, u>());

//!\brief Resolves to `ranges::ImplicitlyConvertibleTo<type1, type2>()`
template <typename t, typename u>
concept bool implicitly_convertible_to_concept =    static_cast<bool>(ranges::ImplicitlyConvertibleTo<t, u>());

//!\brief Resolves to `ranges::ExplicitlyConvertibleTo<type1, type2>()`
template <typename t, typename u>
concept bool explicitly_convertible_to_concept =    static_cast<bool>(ranges::ExplicitlyConvertibleTo<t, u>());

/*!\brief Resolves to `ranges::ConvertibleTo<type1, type2>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/ConvertibleTo
 */
template <typename t, typename u>
concept bool convertible_to_concept =               implicitly_convertible_to_concept<t, u> &&
                                                    explicitly_convertible_to_concept<t, u>;

/*!\brief Resolves to `ranges::CommonReference<type1, type2, rest...>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/CommonReference
 */
template <typename t, typename u, typename ...rest>
concept bool common_reference_concept =             static_cast<bool>(ranges::CommonReference<t, u, rest...>());

/*!\brief Resolves to `ranges::Common<type1, type2, rest...>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/Common
 */
template <typename t, typename u, typename ...rest>
concept bool common_concept =                       static_cast<bool>(ranges::Common<t, u, rest...>());

/*!\brief Resolves to `ranges::Integral<type>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/Integral
 */
template <typename t>
concept bool integral_concept =                     static_cast<bool>(ranges::Integral<t>());

/*!\brief Resolves to `ranges::SignedIntegral<type>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/SignedIntegral
 */
template <typename t>
concept bool signed_integral_concept =              integral_concept<t> &&
                                                    static_cast<bool>(ranges::SignedIntegral<t>());

/*!\brief Resolves to `ranges::UnsignedIntegral<type>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/UnsignedIntegral
 */
template <typename t>
concept bool unsigned_integral_concept =            integral_concept<t> &&
                                                    static_cast<bool>(ranges::UnsignedIntegral<t>());

/*!\brief Resolves to `ranges::Assignable<type1, type2>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/Assignable
 */
template <typename t, typename u>
concept bool assignable_concept =                   static_cast<bool>(ranges::Assignable<t, u>());

/*!\brief Resolves to `ranges::Swappable<type1, type2>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/Swappable
 */
template <typename t, typename u = t>
concept bool swappable_concept =                    static_cast<bool>(ranges::Swappable<t, u>());

//!\}  // Core Language Concepts.

//!\name Comparison concepts.
//!\{

/*!\brief Resolves to `ranges::WeaklyEqualityComparable<type1, type2>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/WeaklyEqualityComparable
 */
template <typename t, typename u>
concept bool weakly_equality_comparable_concept =   static_cast<bool>(ranges::WeaklyEqualityComparable<t, u>());

/*!\brief Resolves to `ranges::EqualityComparable<type1, type2>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/EqualityComparable
 */
template <typename t, typename u = t>
concept bool equality_comparable_concept =          static_cast<bool>(ranges::EqualityComparable<t, u>());

/*!\brief Resolves to `ranges::WeaklyOrdered<type1, type2>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/WeaklyOrdered
 */
template <typename t, typename u = t>
concept bool weakly_ordered_concept =               static_cast<bool>(ranges::WeaklyOrdered<t>());

/*!\brief Resolves to `ranges::TotallyOrdered<type1, type2>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/TotallyOrdered
 */
template <typename t, typename u = t>
concept bool totally_ordered_concept =              equality_comparable_concept<t, u> &&
                                                    weakly_ordered_concept<t, u> &&
                                                    static_cast<bool>(ranges::TotallyOrdered<t, u>());
//!\}  // Comparison Concepts.

//!\name Object Concepts.
//!\{

/*!\brief Resolves to `ranges::Destructible<type>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/Destructible
 */
template <typename t>
concept bool destructible_concept =                 static_cast<bool>(ranges::Destructible<t>());

/*!\brief Resolves to `ranges::Constructible<type, args...>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/Constructible
 */
template <typename t, typename ...args>
concept bool constructible_concept =                destructible_concept<t> &&
                                                    static_cast<bool>(ranges::Constructible<t, args...>());

/*!\brief Resolves to `ranges::DefaultConstructible<type>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/DefaultConstructible
 */
template <typename t>
concept bool default_constructible_concept =        constructible_concept<t> &&
                                                    static_cast<bool>(ranges::DefaultConstructible<t>());

/*!\brief Resolves to `ranges::MoveConstructible<type>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/MoveConstructible
 */
template <typename t>
concept bool move_constructible_concept =           static_cast<bool>(ranges::MoveConstructible<t>());

/*!\brief Resolves to `ranges::CopyConstructible<type>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/CopyConstructible
 */
template <typename t>
concept bool copy_constructible_concept =           move_constructible_concept<t> &&
                                                    static_cast<bool>(ranges::CopyConstructible<t>());

/*!\brief Resolves to `ranges::Movable<types...>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/Movable
 */
template <typename t>
concept bool movable_concept =                      move_constructible_concept<t> &&
                                                    static_cast<bool>(ranges::Movable<t>());

/*!\brief Resolves to `ranges::Copyable<type>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/Copyable
 */
template <typename t>
concept bool copyable_concept =                     movable_concept<t> &&
                                                    copy_constructible_concept<t> &&
                                                    static_cast<bool>(ranges::Copyable<t>());

/*!\brief Resolves to `ranges::SemiRegular<type>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/SemiRegular
 */
template <typename t>
concept bool semi_regular_concept =                 copyable_concept<t> &&
                                                    default_constructible_concept<t>;

/*!\brief Resolves to `ranges::Regular<type>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/Regular
 */
template <typename t>
concept bool regular_concept =                      semi_regular_concept<t> &&
                                                    equality_comparable_concept<t>;
//!\}  Object Concepts.

//!\name Callable Concepts.
//!\{

/*!\brief Resolves to `ranges::Invocable<func, ...args>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/Invocable
 */
template <typename f, typename ...args>
concept bool invocable_concept =                    static_cast<bool>(ranges::Invocable<f, args...>());

/*!\brief Resolves to `ranges::RegularInvocable<func, ...args>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/RegularInvocable
 */
template <typename f, typename ...args>
concept bool regular_invocable_concept =            invocable_concept<f, args...> &&
                                                    static_cast<bool>(ranges::RegularInvocable<f, args...>());

/*!\brief Resolves to `ranges::Predicate<func, ...args>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/Predicate
 */
template <typename f, typename ...args>
concept bool predicate_concept =                    regular_invocable_concept<f, args...> &&
                                                    static_cast<bool>(ranges::Predicate<f, args...>());

/*!\brief Resolves to `ranges::Relation<func, type1, type2>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/Relation
 */
template <typename f, typename t, typename u>
concept bool relation_concept =                     static_cast<bool>(ranges::Relation<f, t, u>());

//!\}  Callable Concepts.

}  // namespace seqan3

#ifndef NDEBUG

#include <seqan3/core/concepts/core_detail.hpp>

#endif // NDEBUG
<commit_msg>[FIX] typo in core concepts<commit_after>// ============================================================================
//                 SeqAn - The Library for Sequence Analysis
// ============================================================================
//
// Copyright (c) 2006-2017, Knut Reinert & Freie Universitaet Berlin
// Copyright (c) 2016-2017, Knut Reinert & MPI Molekulare Genetik
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of Knut Reinert or the FU Berlin nor the names of
//       its contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
// DAMAGE.
//
// ============================================================================

/*!\file core/concept/core.hpp
 * \brief Adaptions of core concepts from the Ranges TS.
 * \ingroup core
 * \author Rene Rahn <rene.rahn AT fu-berlin.de>
 */

#pragma once

#include <range/v3/range_concepts.hpp>
#include <range/v3/utility/functional.hpp>

namespace seqan3
{

//!\name Core Language Concepts
//!\{
/*!\brief Resolves to `ranges::Same<types...>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/Same
 */
template <typename ...ts>
concept bool same_concept =                         static_cast<bool>(ranges::Same<ts...>());

/*!\brief Resolves to `ranges::DerivedFrom<type1, type2>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/DerivedFrom
 */
template <typename t, typename u>
concept bool derived_from_conept =                  static_cast<bool>(ranges::DerivedFrom<t, u>());

//!\brief Resolves to `ranges::ImplicitlyConvertibleTo<type1, type2>()`
template <typename t, typename u>
concept bool implicitly_convertible_to_concept =    static_cast<bool>(ranges::ImplicitlyConvertibleTo<t, u>());

//!\brief Resolves to `ranges::ExplicitlyConvertibleTo<type1, type2>()`
template <typename t, typename u>
concept bool explicitly_convertible_to_concept =    static_cast<bool>(ranges::ExplicitlyConvertibleTo<t, u>());

/*!\brief Resolves to `ranges::ConvertibleTo<type1, type2>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/ConvertibleTo
 */
template <typename t, typename u>
concept bool convertible_to_concept =               implicitly_convertible_to_concept<t, u> &&
                                                    explicitly_convertible_to_concept<t, u>;

/*!\brief Resolves to `ranges::CommonReference<type1, type2, rest...>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/CommonReference
 */
template <typename t, typename u, typename ...rest>
concept bool common_reference_concept =             static_cast<bool>(ranges::CommonReference<t, u, rest...>());

/*!\brief Resolves to `ranges::Common<type1, type2, rest...>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/Common
 */
template <typename t, typename u, typename ...rest>
concept bool common_concept =                       static_cast<bool>(ranges::Common<t, u, rest...>());

/*!\brief Resolves to `ranges::Integral<type>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/Integral
 */
template <typename t>
concept bool integral_concept =                     static_cast<bool>(ranges::Integral<t>());

/*!\brief Resolves to `ranges::SignedIntegral<type>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/SignedIntegral
 */
template <typename t>
concept bool signed_integral_concept =              integral_concept<t> &&
                                                    static_cast<bool>(ranges::SignedIntegral<t>());

/*!\brief Resolves to `ranges::UnsignedIntegral<type>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/UnsignedIntegral
 */
template <typename t>
concept bool unsigned_integral_concept =            integral_concept<t> &&
                                                    static_cast<bool>(ranges::UnsignedIntegral<t>());

/*!\brief Resolves to `ranges::Assignable<type1, type2>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/Assignable
 */
template <typename t, typename u>
concept bool assignable_concept =                   static_cast<bool>(ranges::Assignable<t, u>());

/*!\brief Resolves to `ranges::Swappable<type1, type2>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/Swappable
 */
template <typename t, typename u = t>
concept bool swappable_concept =                    static_cast<bool>(ranges::Swappable<t, u>());

//!\}  // Core Language Concepts.

//!\name Comparison concepts.
//!\{

/*!\brief Resolves to `ranges::WeaklyEqualityComparable<type1, type2>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/WeaklyEqualityComparable
 */
template <typename t, typename u>
concept bool weakly_equality_comparable_concept =   static_cast<bool>(ranges::WeaklyEqualityComparable<t, u>());

/*!\brief Resolves to `ranges::EqualityComparable<type1, type2>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/EqualityComparable
 */
template <typename t, typename u = t>
concept bool equality_comparable_concept =          static_cast<bool>(ranges::EqualityComparable<t, u>());

/*!\brief Resolves to `ranges::WeaklyOrdered<type1, type2>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/WeaklyOrdered
 */
template <typename t, typename u = t>
concept bool weakly_ordered_concept =               static_cast<bool>(ranges::WeaklyOrdered<t>());

/*!\brief Resolves to `ranges::TotallyOrdered<type1, type2>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/TotallyOrdered
 */
template <typename t, typename u = t>
concept bool totally_ordered_concept =              equality_comparable_concept<t, u> &&
                                                    weakly_ordered_concept<t, u> &&
                                                    static_cast<bool>(ranges::TotallyOrdered<t, u>());
//!\}  // Comparison Concepts.

//!\name Object Concepts.
//!\{

/*!\brief Resolves to `ranges::Destructible<type>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/Destructible
 */
template <typename t>
concept bool destructible_concept =                 static_cast<bool>(ranges::Destructible<t>());

/*!\brief Resolves to `ranges::Constructible<type, args...>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/Constructible
 */
template <typename t, typename ...args>
concept bool constructible_concept =                destructible_concept<t> &&
                                                    static_cast<bool>(ranges::Constructible<t, args...>());

/*!\brief Resolves to `ranges::DefaultConstructible<type>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/DefaultConstructible
 */
template <typename t>
concept bool default_constructible_concept =        constructible_concept<t> &&
                                                    static_cast<bool>(ranges::DefaultConstructible<t>());

/*!\brief Resolves to `ranges::MoveConstructible<type>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/MoveConstructible
 */
template <typename t>
concept bool move_constructible_concept =           static_cast<bool>(ranges::MoveConstructible<t>());

/*!\brief Resolves to `ranges::CopyConstructible<type>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/CopyConstructible
 */
template <typename t>
concept bool copy_constructible_concept =           move_constructible_concept<t> &&
                                                    static_cast<bool>(ranges::CopyConstructible<t>());

/*!\brief Resolves to `ranges::Movable<types...>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/Movable
 */
template <typename t>
concept bool movable_concept =                      move_constructible_concept<t> &&
                                                    static_cast<bool>(ranges::Movable<t>());

/*!\brief Resolves to `ranges::Copyable<type>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/Copyable
 */
template <typename t>
concept bool copyable_concept =                     movable_concept<t> &&
                                                    copy_constructible_concept<t> &&
                                                    static_cast<bool>(ranges::Copyable<t>());

/*!\brief Resolves to `ranges::SemiRegular<type>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/SemiRegular
 */
template <typename t>
concept bool semi_regular_concept =                 copyable_concept<t> &&
                                                    default_constructible_concept<t>;

/*!\brief Resolves to `ranges::Regular<type>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/Regular
 */
template <typename t>
concept bool regular_concept =                      semi_regular_concept<t> &&
                                                    equality_comparable_concept<t>;
//!\}  Object Concepts.

//!\name Callable Concepts.
//!\{

/*!\brief Resolves to `ranges::Invocable<func, ...args>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/Invocable
 */
template <typename f, typename ...args>
concept bool invocable_concept =                    static_cast<bool>(ranges::Invocable<f, args...>());

/*!\brief Resolves to `ranges::RegularInvocable<func, ...args>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/RegularInvocable
 */
template <typename f, typename ...args>
concept bool regular_invocable_concept =            invocable_concept<f, args...> &&
                                                    static_cast<bool>(ranges::RegularInvocable<f, args...>());

/*!\brief Resolves to `ranges::Predicate<func, ...args>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/Predicate
 */
template <typename f, typename ...args>
concept bool predicate_concept =                    regular_invocable_concept<f, args...> &&
                                                    static_cast<bool>(ranges::Predicate<f, args...>());

/*!\brief Resolves to `ranges::Relation<func, type1, type2>()`
 * \sa http://en.cppreference.com/w/cpp/experimental/ranges/concepts/Relation
 */
template <typename f, typename t, typename u>
concept bool relation_concept =                     static_cast<bool>(ranges::Relation<f, t, u>());

//!\}  Callable Concepts.

}  // namespace seqan3

#ifndef NDEBUG

#include <seqan3/core/concept/core_detail.hpp>

#endif // NDEBUG
<|endoftext|>


<commit_before>// This file is a part of Simdee, see homepage at http://github.com/tufak/simdee
// This file is distributed under the MIT license.

#ifndef SIMDEE_SIMD_TYPES_COMMON_HPP
#define SIMDEE_SIMD_TYPES_COMMON_HPP

#include "../util/inline.hpp"
#include "../util/bitfiddle.hpp"
#include "../util/macros.hpp"
#include "../common/casts.hpp"
#include "../common/expr.hpp"
#include "../common/mask.hpp"
#include "../common/storage.hpp"
#include "../common/deferred_not.hpp"
#include <array>
#include <type_traits>

namespace sd {

    template <typename T>
    struct is_simd_type : std::integral_constant<bool, false> {};
    template <typename T>
    struct simd_type_traits;

    template <typename Crtp>
    struct simd_base {
        using traits_t = simd_type_traits<Crtp>;
        using vector_t = typename traits_t::vector_t;
        using scalar_t = typename traits_t::scalar_t;
        using element_t = typename traits_t::element_t;
        using mask_t = typename traits_t::mask_t;
        using storage_t = typename traits_t::storage_t;
        using binary_op_t = Crtp(*)(Crtp l, Crtp r);

        enum : std::size_t {
            width = sizeof(vector_t) / sizeof(scalar_t)
        };

        SIMDEE_INL Crtp& self() {
            return static_cast<Crtp&>(*this);
        }

        SIMDEE_INL constexpr const Crtp& self() const {
            return static_cast<const Crtp&>(*this);
        }

        SIMDEE_INL Crtp& eval() {
            return static_cast<Crtp&>(*this);
        }

        SIMDEE_INL constexpr const Crtp& eval() const {
            return static_cast<const Crtp&>(*this);
        }

        vector_t& data() { return mm; }
        const vector_t& data() const { return mm; }

    protected:
        // data
        vector_t mm;
    };

    template <typename Simd_t, typename Rhs_t>
    SIMDEE_INL Simd_t& operator&=(simd_base<Simd_t>& l, const Rhs_t& r) {
        l.self() = l.self() & r;
        return l.self();
    }
    template <typename Simd_t, typename Rhs_t>
    SIMDEE_INL Simd_t& operator|=(simd_base<Simd_t>& l, const Rhs_t& r) {
        l.self() = l.self() | r;
        return l.self();
    }
    template <typename Simd_t, typename Rhs_t>
    SIMDEE_INL Simd_t& operator^=(simd_base<Simd_t>& l, const Rhs_t& r) {
        l.self() = l.self() ^ r;
        return l.self();
    }
    template <typename Simd_t, typename Rhs_t>
    SIMDEE_INL Simd_t& operator+=(simd_base<Simd_t>& l, const Rhs_t& r) {
        l.self() = l.self() + r;
        return l.self();
    }
    template <typename Simd_t, typename Rhs_t>
    SIMDEE_INL Simd_t& operator-=(simd_base<Simd_t>& l, const Rhs_t& r) {
        l.self() = l.self() - r;
        return l.self();
    }
    template <typename Simd_t, typename Rhs_t>
    SIMDEE_INL Simd_t& operator*=(simd_base<Simd_t>& l, const Rhs_t& r) {
        l.self() = l.self() * r;
        return l.self();
    }
    template <typename Simd_t, typename Rhs_t>
    SIMDEE_INL Simd_t& operator/=(simd_base<Simd_t>& l, const Rhs_t& r) {
        l.self() = l.self() / r;
        return l.self();
    }
    template <typename Simd_t>
    SIMDEE_INL const Simd_t operator+(const simd_base<Simd_t>& l) {
        return l.self();
    }
    template <typename Simd_t>
    SIMDEE_INL const Simd_t signum(const simd_base<Simd_t>& l) {
        return cond(l.self() > zero(), Simd_t(1), Simd_t(-1));
    }
    template <typename Simd_t>
    SIMDEE_INL bool any(const simd_base<Simd_t>& l) {
        return l.self().mask().any();
    }
    template <typename Simd_t>
    SIMDEE_INL bool all(const simd_base<Simd_t>& l) {
        return l.self().mask().all();
    }

}

#endif // SIMDEE_SIMD_TYPES_COMMON_HPP
<commit_msg>Make types vec_b, vec_f, etc. accessible in simd_base<commit_after>// This file is a part of Simdee, see homepage at http://github.com/tufak/simdee
// This file is distributed under the MIT license.

#ifndef SIMDEE_SIMD_TYPES_COMMON_HPP
#define SIMDEE_SIMD_TYPES_COMMON_HPP

#include "../util/inline.hpp"
#include "../util/bitfiddle.hpp"
#include "../util/macros.hpp"
#include "../common/casts.hpp"
#include "../common/expr.hpp"
#include "../common/mask.hpp"
#include "../common/storage.hpp"
#include "../common/deferred_not.hpp"
#include <array>
#include <type_traits>

namespace sd {

    template <typename T>
    struct is_simd_type : std::integral_constant<bool, false> {};
    template <typename T>
    struct simd_type_traits;

    template <typename Crtp>
    struct simd_base {
        using traits_t = simd_type_traits<Crtp>;
        using vector_t = typename traits_t::vector_t;
        using scalar_t = typename traits_t::scalar_t;
        using element_t = typename traits_t::element_t;
        using vec_b = typename traits_t::vec_b;
        using vec_f = typename traits_t::vec_f;
        using vec_u = typename traits_t::vec_u;
        using vec_s = typename traits_t::vec_s;
        using mask_t = typename traits_t::mask_t;
        using storage_t = typename traits_t::storage_t;
        using binary_op_t = Crtp(*)(Crtp l, Crtp r);

        enum : std::size_t {
            width = sizeof(vector_t) / sizeof(scalar_t)
        };

        SIMDEE_INL Crtp& self() {
            return static_cast<Crtp&>(*this);
        }

        SIMDEE_INL constexpr const Crtp& self() const {
            return static_cast<const Crtp&>(*this);
        }

        SIMDEE_INL Crtp& eval() {
            return static_cast<Crtp&>(*this);
        }

        SIMDEE_INL constexpr const Crtp& eval() const {
            return static_cast<const Crtp&>(*this);
        }

        vector_t& data() { return mm; }
        const vector_t& data() const { return mm; }

    protected:
        // data
        vector_t mm;
    };

    template <typename Simd_t, typename Rhs_t>
    SIMDEE_INL Simd_t& operator&=(simd_base<Simd_t>& l, const Rhs_t& r) {
        l.self() = l.self() & r;
        return l.self();
    }
    template <typename Simd_t, typename Rhs_t>
    SIMDEE_INL Simd_t& operator|=(simd_base<Simd_t>& l, const Rhs_t& r) {
        l.self() = l.self() | r;
        return l.self();
    }
    template <typename Simd_t, typename Rhs_t>
    SIMDEE_INL Simd_t& operator^=(simd_base<Simd_t>& l, const Rhs_t& r) {
        l.self() = l.self() ^ r;
        return l.self();
    }
    template <typename Simd_t, typename Rhs_t>
    SIMDEE_INL Simd_t& operator+=(simd_base<Simd_t>& l, const Rhs_t& r) {
        l.self() = l.self() + r;
        return l.self();
    }
    template <typename Simd_t, typename Rhs_t>
    SIMDEE_INL Simd_t& operator-=(simd_base<Simd_t>& l, const Rhs_t& r) {
        l.self() = l.self() - r;
        return l.self();
    }
    template <typename Simd_t, typename Rhs_t>
    SIMDEE_INL Simd_t& operator*=(simd_base<Simd_t>& l, const Rhs_t& r) {
        l.self() = l.self() * r;
        return l.self();
    }
    template <typename Simd_t, typename Rhs_t>
    SIMDEE_INL Simd_t& operator/=(simd_base<Simd_t>& l, const Rhs_t& r) {
        l.self() = l.self() / r;
        return l.self();
    }
    template <typename Simd_t>
    SIMDEE_INL const Simd_t operator+(const simd_base<Simd_t>& l) {
        return l.self();
    }
    template <typename Simd_t>
    SIMDEE_INL const Simd_t signum(const simd_base<Simd_t>& l) {
        return cond(l.self() > zero(), Simd_t(1), Simd_t(-1));
    }
    template <typename Simd_t>
    SIMDEE_INL bool any(const simd_base<Simd_t>& l) {
        return l.self().mask().any();
    }
    template <typename Simd_t>
    SIMDEE_INL bool all(const simd_base<Simd_t>& l) {
        return l.self().mask().all();
    }

}

#endif // SIMDEE_SIMD_TYPES_COMMON_HPP
<|endoftext|>


<commit_before>#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <d2d1.h>
#pragma comment(lib, "d2d1")

#include "../../../Nova/nova_geometry.h"
#include "../../../Nova/nova_render.h"

LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

// Direct 2D vars.
ID2D1Factory *pFactory = NULL;
ID2D1HwndRenderTarget *pRenderTarget = NULL;
ID2D1Bitmap *bm = NULL;
HRESULT CreateD2D(HWND hWnd);
void DestroyD2D();

// My vars.
Mesh *mesh;
Matrix pos, persp;

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR pCmdLine, int nCmdShow)
{
	// Register the window class.
	WNDCLASS wc = { 0 };
	wc.lpfnWndProc = WindowProc;
	wc.hInstance = hInstance;
	wc.lpszClassName = L"Nova Window";
	RegisterClass(&wc);

	// Create the window.
	HWND hWnd = CreateWindowEx(0, wc.lpszClassName, L"Nova", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 600, 600, NULL, NULL, hInstance, NULL);
	if (hWnd == NULL)
		return -1;
	ShowWindow(hWnd, nCmdShow);

	if (FAILED(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &pFactory)))
		return -1;

	// Set up my stuff.
	mesh = CreateMeshFromFile("../../../models/bunny-1500.obj");
	if (!mesh)
		MessageBox(NULL, L"ERROR", L"Unable to load mesh file!", MB_OK);

	MatSetTranslate(&pos, 0.0f, -0.1f, -0.3f);

	// Run the message loop.
	MSG msg = { 0 };
	DWORD start = GetTickCount();
	DWORD now;
	int frame = 0;
	wchar_t d[20];
	while (msg.message != WM_QUIT)
	{
		while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}

		InvalidateRect(hWnd, NULL, FALSE);

		frame++;
		now = GetTickCount();
		if (now - start > 2000)
		{
			start = now;
			_itow_s(frame / 2, d, 20, 10);
			SetWindowText(hWnd, d);
			frame = 0;
		}
	}

	if (pFactory)
	{
		pFactory->Release();
		pFactory = NULL;
	}

	DestroyD2D();
	DestroyMesh(mesh);

	return 0;
}

HRESULT CreateD2D(HWND hWnd)
{
	HRESULT hr = S_OK;

	if (pRenderTarget == NULL)
	{
		RECT rc;
		GetClientRect(hWnd, &rc);

		D2D1_SIZE_U size = D2D1::SizeU(rc.right, rc.bottom);

		hr = pFactory->CreateHwndRenderTarget(D2D1::RenderTargetProperties(), D2D1::HwndRenderTargetProperties(hWnd, size, D2D1_PRESENT_OPTIONS_IMMEDIATELY), &pRenderTarget);

		if (SUCCEEDED(hr))
		{
			D2D1_PIXEL_FORMAT pf = pRenderTarget->GetPixelFormat();
			D2D1_BITMAP_PROPERTIES bmp = D2D1::BitmapProperties(pf);
			hr = pRenderTarget->CreateBitmap(pRenderTarget->GetPixelSize(), bmp, &bm);
		}
	}

	return hr;
}

void DestroyD2D()
{
	if (pRenderTarget != NULL)
	{
		pRenderTarget->Release();
		pRenderTarget = NULL;
	}
	if (bm != NULL)
	{
		bm->Release();
		bm = NULL;
	}
}

LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg)
	{
	case WM_CREATE:

		return 0;

	case WM_DESTROY:
		PostQuitMessage(0);

		return 0;

	case WM_PAINT:
	{
		if (pRenderTarget == NULL)
		{
			CreateD2D(hWnd);

			D2D1_PIXEL_FORMAT pf = pRenderTarget->GetPixelFormat();
			float dpix, dpiy;
			pRenderTarget->GetDpi(&dpix, &dpiy);
			D2D1_BITMAP_PROPERTIES bmp = D2D1::BitmapProperties(pf, dpix, dpiy);
			RECT rc;
			GetClientRect(hWnd, &rc);
			pRenderTarget->CreateBitmap(D2D1::SizeU(rc.right, rc.bottom), bmp, &bm);
		}

		PAINTSTRUCT ps;
		HDC hdc = BeginPaint(hWnd, &ps);

		pRenderTarget->BeginDraw();

		clear_pixel_buffer();
		clear_depth_buffer();

		if (mesh != NULL)
			RenderMesh(mesh, &pos);

		RECT rc;
		GetClientRect(hWnd, &rc);
		D2D1_RECT_U rect = D2D1::RectU(0, 0, rc.right, rc.bottom);
		uint32_t *src = get_pixel_buffer();
		HRESULT hr = bm->CopyFromMemory(NULL, src, rc.right * sizeof(uint32_t));
		pRenderTarget->DrawBitmap(bm);

		hr = pRenderTarget->EndDraw();
		if (hr == D2DERR_RECREATE_TARGET)
			DestroyD2D();

		EndPaint(hWnd, &ps);
	}
	return 0;

	case WM_SIZE:
		RECT rc;
		GetClientRect(hWnd, &rc);

		DestroyD2D();

		set_screen_size(rc.right, rc.bottom);
		set_fov(60.0f);

		return 0;
	}

	return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
<commit_msg>Fixed issue with triangle rendering<commit_after>#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <d2d1.h>
#pragma comment(lib, "d2d1")

#include "../../../Nova/nova_geometry.h"
#include "../../../Nova/nova_render.h"

LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

// Direct 2D vars.
ID2D1Factory *pFactory = NULL;
ID2D1HwndRenderTarget *pRenderTarget = NULL;
ID2D1Bitmap *bm = NULL;
HRESULT CreateD2D(HWND hWnd);
void DestroyD2D();

// My vars.
Mesh *mesh;
Matrix pos, persp;

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR pCmdLine, int nCmdShow)
{
	// Register the window class.
	WNDCLASS wc = { 0 };
	wc.lpfnWndProc = WindowProc;
	wc.hInstance = hInstance;
	wc.lpszClassName = L"Nova Window";
	RegisterClass(&wc);

	// Create the window.
	HWND hWnd = CreateWindowEx(0, wc.lpszClassName, L"Nova", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 600, 600, NULL, NULL, hInstance, NULL);
	if (hWnd == NULL)
		return -1;
	ShowWindow(hWnd, nCmdShow);

	if (FAILED(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &pFactory)))
		return -1;

	// Set up my stuff.
	mesh = CreateMeshFromFile("../../../models/bunny-5000.obj");
	if (!mesh)
		MessageBox(NULL, L"ERROR", L"Unable to load mesh file!", MB_OK);

	// Run the message loop.
	MSG msg = { 0 };
	DWORD start = GetTickCount();
	DWORD now;
	int frame = 0;
	wchar_t d[20];
	while (msg.message != WM_QUIT)
	{
		while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}

		static float ang = 0.0f;
		//ang += 0.0025f;
		Matrix rot, trans;
		MatSetRotY(&rot, ang);
		MatSetTranslate(&trans, 0.0f, -0.1f, -0.35f);
		MatMul(&trans, &rot, &pos);

		InvalidateRect(hWnd, NULL, FALSE);

		frame++;
		now = GetTickCount();
		if (now - start > 2000)
		{
			start = now;
			_itow_s(frame / 2, d, 20, 10);
			SetWindowText(hWnd, d);
			frame = 0;
		}
	}

	if (pFactory)
	{
		pFactory->Release();
		pFactory = NULL;
	}

	DestroyD2D();
	DestroyMesh(mesh);

	return 0;
}

HRESULT CreateD2D(HWND hWnd)
{
	HRESULT hr = S_OK;

	if (pRenderTarget == NULL)
	{
		RECT rc;
		GetClientRect(hWnd, &rc);

		D2D1_SIZE_U size = D2D1::SizeU(rc.right, rc.bottom);

		hr = pFactory->CreateHwndRenderTarget(D2D1::RenderTargetProperties(), D2D1::HwndRenderTargetProperties(hWnd, size, D2D1_PRESENT_OPTIONS_IMMEDIATELY), &pRenderTarget);

		if (SUCCEEDED(hr))
		{
			D2D1_PIXEL_FORMAT pf = pRenderTarget->GetPixelFormat();
			D2D1_BITMAP_PROPERTIES bmp = D2D1::BitmapProperties(pf);
			hr = pRenderTarget->CreateBitmap(pRenderTarget->GetPixelSize(), bmp, &bm);
		}
	}

	return hr;
}

void DestroyD2D()
{
	if (pRenderTarget != NULL)
	{
		pRenderTarget->Release();
		pRenderTarget = NULL;
	}
	if (bm != NULL)
	{
		bm->Release();
		bm = NULL;
	}
}

LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg)
	{
	case WM_CREATE:

		return 0;

	case WM_DESTROY:
		PostQuitMessage(0);

		return 0;

	case WM_PAINT:
	{
		if (pRenderTarget == NULL)
		{
			CreateD2D(hWnd);

			D2D1_PIXEL_FORMAT pf = pRenderTarget->GetPixelFormat();
			float dpix, dpiy;
			pRenderTarget->GetDpi(&dpix, &dpiy);
			D2D1_BITMAP_PROPERTIES bmp = D2D1::BitmapProperties(pf, dpix, dpiy);
			RECT rc;
			GetClientRect(hWnd, &rc);
			pRenderTarget->CreateBitmap(D2D1::SizeU(rc.right, rc.bottom), bmp, &bm);
		}

		PAINTSTRUCT ps;
		HDC hdc = BeginPaint(hWnd, &ps);

		pRenderTarget->BeginDraw();

		clear_pixel_buffer();
		clear_depth_buffer();

		if (mesh != NULL)
			RenderMesh(mesh, &pos);

		RECT rc;
		GetClientRect(hWnd, &rc);
		D2D1_RECT_U rect = D2D1::RectU(0, 0, rc.right, rc.bottom);
		uint32_t *src = get_pixel_buffer();
		HRESULT hr = bm->CopyFromMemory(NULL, src, rc.right * sizeof(uint32_t));
		pRenderTarget->DrawBitmap(bm);

		hr = pRenderTarget->EndDraw();
		if (hr == D2DERR_RECREATE_TARGET)
			DestroyD2D();

		EndPaint(hWnd, &ps);
	}
	return 0;

	case WM_SIZE:
		RECT rc;
		GetClientRect(hWnd, &rc);

		DestroyD2D();

		set_screen_size(rc.right, rc.bottom);
		set_fov(60.0f);

		return 0;
	}

	return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
<|endoftext|>