<commit_before>#pragma once

#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include <typeinfo>
#include <cxxabi.h>
#include <sys/time.h>
#include <stdarg.h>

#include <zcm/zcm-cpp.hpp>
#include <zcm/util/circular.hpp>

static bool ZCM_DEBUG_ENABLED = (NULL != getenv("ZCM_DEBUG"));
#define ZCM_DEBUG(...) \
    do {\
        __ZCM_PRINT_OBFUSCATE__(std::cout, "ZCM-DEBUG: ", __VA_ARGS__, '\n'); \
    } while(0)

template <typename T>
class MessageTracker
{
  public:
    typedef void (*callback)(const T* msg, void* usr);

  private:
    zcm::ZCM* zcmLocal = nullptr;

    std::atomic_bool done {false};

    Circular<T> *buf;
    std::mutex bufLock;
    std::condition_variable newMsg;
    zcm::Subscription *s;

    std::thread *thr = nullptr;
    callback onMsg;
    void* usr;

    uint64_t maxTimeErr_us;

    void callbackThreadFunc()
    {
        while (!done) {
            T* localMsg = get();
            if (done) return;
            onMsg(localMsg, usr);
        }
    }

    void handle(const zcm::ReceiveBuffer* rbuf, const std::string& chan, const T* _msg)
    {
        if (done)
            return;

        T* tmp = new T(*_msg);

        {
            std::unique_lock<std::mutex> lk(bufLock);

            if (buf->isFull())
                buf->removeFront();

            while (!buf->isEmpty()) {
                if (getMsgUtime(buf->front()) + maxTimeErr_us > getMsgUtime(_msg))
                    break;
                buf->removeFront();
            }

            buf->pushBack(tmp);
        }
        newMsg.notify_all();
    }

    MessageTracker() {}

  protected:
    virtual uint64_t getMsgUtime(const T* msg)
    {
        return hasUtime<T>::utime(msg);
    }

    virtual T* interpolate(uint64_t utimeTarget,
                           const T* A, uint64_t utimeA,
                           const T* B, uint64_t utimeB)
    {
        return utimeTarget - utimeA < utimeB - utimeTarget ? new T(*A) : new T(*B);
    }

  public:
    static const bool NONBLOCKING = false;
    static const bool BLOCKING = true;

    MessageTracker(zcm::ZCM* zcmLocal, std::string channel,
                   uint64_t maxTimeErr_us = 0.25e6, size_t maxMsgs = 1,
                   callback onMsg = nullptr, void* usr = nullptr)
        : zcmLocal(zcmLocal), maxTimeErr_us(maxTimeErr_us), onMsg(onMsg), usr(usr)
    {
        if (hasUtime<T>::present == true) {
            T tmp;
            std::string name = demangle(getType(tmp));
            ZCM_DEBUG("Message trackers using 'utime' field of zcmtype ", name);
        } else {
            T tmp;
            std::string name = demangle(getType(tmp));
            ZCM_DEBUG("Message trackers using local system receive utime for ",
                      "tracking zcmtype ", name);
        }
        buf = new Circular<T>(maxMsgs);
        if (onMsg != nullptr)
            thr = new std::thread(&MessageTracker<T>::callbackThreadFunc, this);
        s = zcmLocal->subscribe(channel, &MessageTracker<T>::handle, this);
    }

    virtual ~MessageTracker()
    {
        zcmLocal->unsubscribe(s);
        done = true;
        newMsg.notify_all();
        if (thr) {
            thr->join();
            delete thr;
        }
        while (!buf->isEmpty())
            buf->removeFront();
        delete buf;
    }

    // You must free the memory returned here
    virtual T* get(bool blocking = NONBLOCKING)
    {
        T* ret = nullptr;

        {
            std::unique_lock<std::mutex> lk(bufLock);
            if (blocking == BLOCKING) {
                if (buf->isEmpty())
                    newMsg.wait(lk, [&]{ return !buf->isEmpty() || done; });
                if (done) return nullptr;
            }
            if (!buf->isEmpty())
                ret = new T(*buf->back());
        }

        return ret;
    }

    virtual T* get(uint64_t utime, bool blocking = NONBLOCKING)
    {
        T *m0 = nullptr, *m1 = nullptr; // two poses bracketing the desired utime
        uint64_t m0Utime, m1Utime;

        {
            std::unique_lock<std::mutex> lk(bufLock);

            if (blocking == BLOCKING) {
                if (buf->isEmpty())
                    newMsg.wait(lk, [&]{ return !buf->isEmpty() || done; });
                if (done) return nullptr;
            }

            size_t size = buf->size();

            const T *_m0 = nullptr;
            const T *_m1 = nullptr;

            for (size_t i = 0; i < size; ++i) {
                const T* m = (*buf)[i];
                uint64_t mUtime = getMsgUtime(m);

                if (mUtime <= utime && (_m0 == nullptr || mUtime > m0Utime)) {
                    _m0 = m;
                    m0Utime = getMsgUtime(_m0);
                }

                if (mUtime >= utime && (_m1 == nullptr || mUtime < m1Utime)) {
                    _m1 = m;
                    m1Utime = getMsgUtime(_m1);
                }
            }

            if (_m0 != nullptr)
                m0 = new T(*_m0);

            if (_m1 != nullptr)
                m1 = new T(*_m1);

        }

        if (m0 && utime - m0Utime > maxTimeErr_us) {
            delete m0;
            m0 = nullptr;
        }

        if (m1 && m1Utime - utime > maxTimeErr_us) {
            delete m1;
            m1 = nullptr;
        }

        if (m0 && m1) {
            if (m0Utime == m1Utime) {
                delete m1;
                return m0;
            }

            T* elt = interpolate(utime, m0, m0Utime, m1, m1Utime);

            delete m0;
            delete m1;

            return elt;
        }

        if (m0) return m0;
        if (m1) return m1;

        return nullptr;
    }

  private:
    // *****************************************************************************
    // Insanely hacky trick to determine at compile time if a zcmtype has a
    // field called "utime"
    template <typename F> struct hasUtime {
        struct Fallback { void* utime; }; // introduce member name "utime"
        struct Derived : F, Fallback {};

        template <typename C, C> struct ChT;

        template <typename C>
        static uint64_t _utime(ChT<void* Fallback::*, &C::utime>*, const F* msg)
        {
            struct timeval tv;
            gettimeofday(&tv, NULL);
            return (uint64_t)tv.tv_sec * 1000000 + tv.tv_usec;
        };
        template <typename C>
        static uint64_t _utime(void*, ...)
        {
            va_list args;
            va_start(args, 1);
            const F* msg = va_arg(args, const F*);
            va_end(args);
            return msg->utime;
        }

        template<typename C> static char (&f(ChT<int Fallback::*, &C::x>*))[1];
        template<typename C> static char (&f(...))[2];

        static bool const present = sizeof(f<Derived>(0)) == 2;

        static uint64_t const utime(const F* msg)
        {
            return _utime<Derived>(0,msg);
        }
    };

    template<typename F>
    static inline std::string getType(const F t) { return typeid(t).name(); }

    static inline std::string demangle(std::string name)
    {
        int status = -4; // some arbitrary value to eliminate the compiler warning
        std::unique_ptr<char, void(*)(void*)> res {
            abi::__cxa_demangle(name.c_str(), NULL, NULL, &status),
            std::free
        };
        return (status==0) ? res.get() : name ;
    }

    static void __ZCM_PRINT_OBFUSCATE__(std::ostream& o) { }

    template<typename First, typename ...Rest>
    static void __ZCM_PRINT_OBFUSCATE__(std::ostream& o, First && first, Rest && ...rest)
    {
        o << std::forward<First>(first);
        __ZCM_PRINT_OBFUSCATE__(o, std::forward<Rest>(rest)...);
    }
    // *****************************************************************************

};

#undef ZCM_DEBUG
<commit_msg>Printing only when printing enabled<commit_after>#pragma once

#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include <typeinfo>
#include <cxxabi.h>
#include <sys/time.h>
#include <stdarg.h>

#include <zcm/zcm-cpp.hpp>
#include <zcm/util/circular.hpp>

static bool ZCM_DEBUG_ENABLED = (NULL != getenv("ZCM_DEBUG"));
#define ZCM_DEBUG(...) \
    do { \
        if (ZCM_DEBUG_ENABLED) \
            __ZCM_PRINT_OBFUSCATE__(std::cout, "ZCM-DEBUG: ", __VA_ARGS__, '\n'); \
    } while(0)

template <typename T>
class MessageTracker
{
  public:
    typedef void (*callback)(const T* msg, void* usr);

  private:
    zcm::ZCM* zcmLocal = nullptr;

    std::atomic_bool done {false};

    Circular<T> *buf;
    std::mutex bufLock;
    std::condition_variable newMsg;
    zcm::Subscription *s;

    std::thread *thr = nullptr;
    callback onMsg;
    void* usr;

    uint64_t maxTimeErr_us;

    void callbackThreadFunc()
    {
        while (!done) {
            T* localMsg = get();
            if (done) return;
            onMsg(localMsg, usr);
        }
    }

    void handle(const zcm::ReceiveBuffer* rbuf, const std::string& chan, const T* _msg)
    {
        if (done)
            return;

        T* tmp = new T(*_msg);

        {
            std::unique_lock<std::mutex> lk(bufLock);

            if (buf->isFull())
                buf->removeFront();

            while (!buf->isEmpty()) {
                if (getMsgUtime(buf->front()) + maxTimeErr_us > getMsgUtime(_msg))
                    break;
                buf->removeFront();
            }

            buf->pushBack(tmp);
        }
        newMsg.notify_all();
    }

    MessageTracker() {}

  protected:
    virtual uint64_t getMsgUtime(const T* msg)
    {
        return hasUtime<T>::utime(msg);
    }

    virtual T* interpolate(uint64_t utimeTarget,
                           const T* A, uint64_t utimeA,
                           const T* B, uint64_t utimeB)
    {
        return utimeTarget - utimeA < utimeB - utimeTarget ? new T(*A) : new T(*B);
    }

  public:
    static const bool NONBLOCKING = false;
    static const bool BLOCKING = true;

    MessageTracker(zcm::ZCM* zcmLocal, std::string channel,
                   uint64_t maxTimeErr_us = 0.25e6, size_t maxMsgs = 1,
                   callback onMsg = nullptr, void* usr = nullptr)
        : zcmLocal(zcmLocal), maxTimeErr_us(maxTimeErr_us), onMsg(onMsg), usr(usr)
    {
        if (hasUtime<T>::present == true) {
            T tmp;
            std::string name = demangle(getType(tmp));
            ZCM_DEBUG("Message trackers using 'utime' field of zcmtype ", name);
        } else {
            T tmp;
            std::string name = demangle(getType(tmp));
            ZCM_DEBUG("Message trackers using local system receive utime for ",
                      "tracking zcmtype ", name);
        }
        buf = new Circular<T>(maxMsgs);
        if (onMsg != nullptr)
            thr = new std::thread(&MessageTracker<T>::callbackThreadFunc, this);
        s = zcmLocal->subscribe(channel, &MessageTracker<T>::handle, this);
    }

    virtual ~MessageTracker()
    {
        zcmLocal->unsubscribe(s);
        done = true;
        newMsg.notify_all();
        if (thr) {
            thr->join();
            delete thr;
        }
        while (!buf->isEmpty())
            buf->removeFront();
        delete buf;
    }

    // You must free the memory returned here
    virtual T* get(bool blocking = NONBLOCKING)
    {
        T* ret = nullptr;

        {
            std::unique_lock<std::mutex> lk(bufLock);
            if (blocking == BLOCKING) {
                if (buf->isEmpty())
                    newMsg.wait(lk, [&]{ return !buf->isEmpty() || done; });
                if (done) return nullptr;
            }
            if (!buf->isEmpty())
                ret = new T(*buf->back());
        }

        return ret;
    }

    virtual T* get(uint64_t utime, bool blocking = NONBLOCKING)
    {
        T *m0 = nullptr, *m1 = nullptr; // two poses bracketing the desired utime
        uint64_t m0Utime, m1Utime;

        {
            std::unique_lock<std::mutex> lk(bufLock);

            if (blocking == BLOCKING) {
                if (buf->isEmpty())
                    newMsg.wait(lk, [&]{ return !buf->isEmpty() || done; });
                if (done) return nullptr;
            }

            size_t size = buf->size();

            const T *_m0 = nullptr;
            const T *_m1 = nullptr;

            for (size_t i = 0; i < size; ++i) {
                const T* m = (*buf)[i];
                uint64_t mUtime = getMsgUtime(m);

                if (mUtime <= utime && (_m0 == nullptr || mUtime > m0Utime)) {
                    _m0 = m;
                    m0Utime = getMsgUtime(_m0);
                }

                if (mUtime >= utime && (_m1 == nullptr || mUtime < m1Utime)) {
                    _m1 = m;
                    m1Utime = getMsgUtime(_m1);
                }
            }

            if (_m0 != nullptr)
                m0 = new T(*_m0);

            if (_m1 != nullptr)
                m1 = new T(*_m1);

        }

        if (m0 && utime - m0Utime > maxTimeErr_us) {
            delete m0;
            m0 = nullptr;
        }

        if (m1 && m1Utime - utime > maxTimeErr_us) {
            delete m1;
            m1 = nullptr;
        }

        if (m0 && m1) {
            if (m0Utime == m1Utime) {
                delete m1;
                return m0;
            }

            T* elt = interpolate(utime, m0, m0Utime, m1, m1Utime);

            delete m0;
            delete m1;

            return elt;
        }

        if (m0) return m0;
        if (m1) return m1;

        return nullptr;
    }

  private:
    // *****************************************************************************
    // Insanely hacky trick to determine at compile time if a zcmtype has a
    // field called "utime"
    template <typename F> struct hasUtime {
        struct Fallback { void* utime; }; // introduce member name "utime"
        struct Derived : F, Fallback {};

        template <typename C, C> struct ChT;

        template <typename C>
        static uint64_t _utime(ChT<void* Fallback::*, &C::utime>*, const F* msg)
        {
            struct timeval tv;
            gettimeofday(&tv, NULL);
            return (uint64_t)tv.tv_sec * 1000000 + tv.tv_usec;
        };
        template <typename C>
        static uint64_t _utime(void*, ...)
        {
            va_list args;
            va_start(args, 1);
            const F* msg = va_arg(args, const F*);
            va_end(args);
            return msg->utime;
        }

        template<typename C> static char (&f(ChT<int Fallback::*, &C::x>*))[1];
        template<typename C> static char (&f(...))[2];

        static bool const present = sizeof(f<Derived>(0)) == 2;

        static uint64_t const utime(const F* msg)
        {
            return _utime<Derived>(0,msg);
        }
    };

    template<typename F>
    static inline std::string getType(const F t) { return typeid(t).name(); }

    static inline std::string demangle(std::string name)
    {
        int status = -4; // some arbitrary value to eliminate the compiler warning
        std::unique_ptr<char, void(*)(void*)> res {
            abi::__cxa_demangle(name.c_str(), NULL, NULL, &status),
            std::free
        };
        return (status==0) ? res.get() : name ;
    }

    static void __ZCM_PRINT_OBFUSCATE__(std::ostream& o) { }

    template<typename First, typename ...Rest>
    static void __ZCM_PRINT_OBFUSCATE__(std::ostream& o, First && first, Rest && ...rest)
    {
        o << std::forward<First>(first);
        __ZCM_PRINT_OBFUSCATE__(o, std::forward<Rest>(rest)...);
    }
    // *****************************************************************************

};

#undef ZCM_DEBUG
<|endoftext|>


<commit_before>/***********************************************
 * Author: Jun Jiang - jiangjun4@sina.com
 * Create: 2017-07-26 13:27
 * Last modified : 2017-07-26 13:27
 * Filename      : MatrixOperator.cpp
 * Description   :
 **********************************************/

#include <string.h>
#include "algebra/Matrix.h"
#include "utils/ParallelOperator.h"

using abcdl::utils::ParallelOperator;

namespace abcdl{
namespace algebra{

template<class T>
T& Matrix<T>::operator [] (const size_t idx) const{
    CHECK(idx < get_size());
	return _data[idx];
}

template<class T>
bool Matrix<T>::operator == (const Matrix<T>& mat) const{
	if(this == &mat){
		return true;
	}
	if(get_size() != mat.get_size()){
		return false;
	}

    bool result_value = true;
    auto lamda = [](bool* a, const T& b, const T& c){*a = (b == c);};
    utils::ParallelOperator po;
    po.parallel_reduce_boolean<T>(&result_value, _data, get_size(), mat.data(), mat.get_size(), lamda);
	return result_value;
}

template<class T>
Matrix<T>& Matrix<T>::operator = (const T& value){
    reset(value);
    return *this;
}

template<class T>
Matrix<T>& Matrix<T>::operator = (const Matrix<T>& mat){
    if(this != &mat){
        if(get_size() != mat.get_size()){
            if(_data != nullptr){
                delete[] _data;
            }
        	_data = new T[mat.get_size()];
        }

        _rows = mat.rows();
        _cols = mat.cols();
        memcpy(_data, mat.data(), sizeof(T) * mat.get_size());
    }
    return *this;
}

template<class T>
Matrix<T> Matrix<T>::operator + (const T& value) const{
    auto lamda = [](T* a, const T& b){ if(b != 0){*a += b;} };
    Matrix<T> mat;
    clone(mat);
    ParallelOperator po;
    po.parallel_mul2one<T>(mat.data(), mat.get_size(), value, lamda);
    return mat;
}

template<class T>
Matrix<T> Matrix<T>::operator + (const Matrix<T>& mat_a) const{
    CHECK(equal_shape(mat_a));
    auto lamda = [](T* a, const T& b){ if(b != 0){*a += b;} };
    Matrix<T> mat;
    clone(mat);
    ParallelOperator po;
    po.parallel_mul2mul<T>(mat.data(), mat.get_size(), mat_a.data(), mat_a.get_size(), lamda);
    return mat;
}

template<class T>
Matrix<T>& Matrix<T>::operator += (const T& value){
    auto lamda = [](T* a, const T& b){ if(b != 0){ *a += b;} };
    ParallelOperator po;
    po.parallel_mul2one<T>(_data, get_size(), value, lamda);
    return *this;
}
template<class T>
Matrix<T>& Matrix<T>::operator += (const Matrix<T>& mat){
    if(get_size() == 0){
        set_data(mat);
        return *this;
    }
    CHECK(equal_shape(mat));
    auto lamda = [](T* a, const T& b){ if(b != 0){*a += b;} };
    ParallelOperator po;
    po.parallel_mul2mul<T>(_data, get_size(), mat.data(), mat.get_size(), lamda);
    return *this;
}

template<class T>
Matrix<T> Matrix<T>::operator - (const T& value) const{
    auto lamda = [](T* a, const T& b){ if(b != 0){*a -= b;} };
    Matrix<T> mat;
    clone(mat);
    ParallelOperator po;
    po.parallel_mul2one<T>(mat.data(), mat.get_size(), value, lamda);
    return mat;
}

template<class T>
Matrix<T> Matrix<T>::operator - (const Matrix<T>& mat_a) const{
    CHECK(equal_shape(mat_a));
    auto lamda = [](T* a, const T& b){ if(b != 0){*a -= b;} };
    Matrix<T> mat;
    clone(mat);
    ParallelOperator po;
    po.parallel_mul2mul<T>(mat.data(), get_size(), mat_a.data(), mat_a.get_size(), lamda);
    return mat;
}

template<class T>
Matrix<T>& Matrix<T>::operator -= (const T& value){
    auto lamda = [](T* a, const T& b){ if(b != 0){*a -= b;} };
    ParallelOperator po;
    po.parallel_mul2one<T>(_data, get_size(), value, lamda);
	return *this;
}

template<class T>
Matrix<T>& Matrix<T>::operator -= (const Matrix<T>& mat){
    CHECK(equal_shape(mat));
    auto lamda = [](T* a, const T& b){ if(b != 0){*a -= b;} };
    ParallelOperator po;
    po.parallel_mul2mul<T>(_data, get_size(), mat.data(), mat.get_size(), lamda);
	return *this;
}

template<class T>
Matrix<T> Matrix<T>::operator * (const T& value) const{
    auto lamda = [](T* a, const T& b){ if(b != 0){*a *= b;} };
    Matrix<T> mat;
    clone(mat);
    ParallelOperator po;
    po.parallel_mul2one<T>(mat.data(), get_size(), value, lamda);
    return mat;
}

template<class T>
Matrix<T> Matrix<T>::operator * (const Matrix<T>& mat_a) const{
    CHECK(equal_shape(mat_a));
    auto lamda = [](T* a, const T& b){ *a *= b; };
    Matrix<T> mat;
    clone(mat);
    ParallelOperator po;
    po.parallel_mul2mul<T>(mat.data(), get_size(), mat.data(), mat.get_size(), lamda);
    return mat;
}

template<class T>
Matrix<T>& Matrix<T>::operator *= (const T& value){
    auto lamda = [](T* a, const T& b){ *a *= b; };
    ParallelOperator po;
    po.parallel_mul2one<T>(_data, get_size(), value, lamda);
	return *this;
}

template<class T>
Matrix<T>& Matrix<T>::operator *= (const Matrix<T>& mat){
    CHECK(equal_shape(mat));
    auto lamda = [](T* a, const T& b){ *a *= b; };
    ParallelOperator po;
    po.parallel_mul2mul<T>(_data, get_size(), mat.data(), mat.get_size(), lamda);
	return *this;
}

template<class T>
Matrix<T> Matrix<T>::operator / (const T& value) const{
    auto lamda = [](T* a, const T& b){ *a /= b; };
    Matrix<T> mat;
    clone(mat);
    ParallelOperator po;
    po.parallel_mul2one<T>(mat.data(), get_size(), value, lamda);
    return mat;
}

template<class T>
Matrix<T> Matrix<T>::operator / (const Matrix<T>& mat_a) const{
    CHECK(equal_shape(mat_a));
    auto lamda = [](T* a, const T& b){ *a /= b; };
    Matrix<T> mat;
    clone(mat);
    ParallelOperator po;
    po.parallel_mul2mul<T>(mat.data(), mat.get_size(), mat_a.data(), mat_a.get_size(), lamda);
    return mat;
}

template<class T>
Matrix<T>& Matrix<T>::operator /= (const T& value){
    auto lamda = [](T* a, const T& b){ *a /= b; };
    ParallelOperator po;
    po.parallel_mul2one<T>(_data, get_size(), value, lamda);
	return *this;
}

template<class T>
Matrix<T>& Matrix<T>::operator /= (const Matrix<T>& mat){
    CHECK(equal_shape(mat));
    auto lamda = [](T* a, const T& b){ *a /= b; };
    ParallelOperator po;
    po.parallel_mul2mul<T>(_data, get_size(), mat.data(), mat.get_size(), lamda);
	return *this;
}

template class Matrix<int>;
template class Matrix<float>;
template class Matrix<double>;
}//namespace algebra
}//namespace abcdl
<commit_msg>initialized<commit_after>/***********************************************
 * Author: Jun Jiang - jiangjun4@sina.com
 * Create: 2017-07-26 13:27
 * Last modified : 2017-07-26 13:27
 * Filename      : MatrixOperator.cpp
 * Description   :
 **********************************************/

#include <string.h>
#include "algebra/Matrix.h"
#include "utils/ParallelOperator.h"

using abcdl::utils::ParallelOperator;

namespace abcdl{
namespace algebra{

template<class T>
T& Matrix<T>::operator [] (const size_t idx) const{
    CHECK(idx < get_size());
	return _data[idx];
}

template<class T>
bool Matrix<T>::operator == (const Matrix<T>& mat) const{
	if(this == &mat){
		return true;
	}
	if(get_size() != mat.get_size()){
		return false;
	}

    bool result_value = true;
    auto lamda = [](bool* a, const T& b, const T& c){*a = (b == c);};
    utils::ParallelOperator po;
    po.parallel_reduce_boolean<T>(&result_value, _data, get_size(), mat.data(), mat.get_size(), lamda);
	return result_value;
}

template<class T>
Matrix<T>& Matrix<T>::operator = (const T& value){
    reset(value);
    return *this;
}

template<class T>
Matrix<T>& Matrix<T>::operator = (const Matrix<T>& mat){
    if(this != &mat){
        if(get_size() != mat.get_size()){
            if(_data != nullptr){
                delete[] _data;
            }
        	_data = new T[mat.get_size()];
        }

        _rows = mat.rows();
        _cols = mat.cols();
        memcpy(_data, mat.data(), sizeof(T) * mat.get_size());
    }
    return *this;
}

template<class T>
Matrix<T> Matrix<T>::operator + (const T& value) const{
    auto lamda = [](T* a, const T& b){ if(b != 0){*a += b;} };
    Matrix<T> mat;
    clone(mat);
    ParallelOperator po;
    po.parallel_mul2one<T>(mat.data(), mat.get_size(), value, lamda);
    return mat;
}

template<class T>
Matrix<T> Matrix<T>::operator + (const Matrix<T>& mat_a) const{
    Matrix<T> mat;
    if(get_size() == 0){
        mat.set_data(mat_a);
        return mat;
    }

    CHECK(equal_shape(mat_a));
    auto lamda = [](T* a, const T& b){ if(b != 0){*a += b;} };
    clone(mat);
    ParallelOperator po;
    po.parallel_mul2mul_repeat<T>(mat.data(), mat.get_size(), mat_a.data(), mat_a.get_size(), lamda);
    return mat;
}

template<class T>
Matrix<T>& Matrix<T>::operator += (const T& value){
    auto lamda = [](T* a, const T& b){ if(b != 0){ *a += b;} };
    ParallelOperator po;
    po.parallel_mul2one<T>(_data, get_size(), value, lamda);
    return *this;
}
template<class T>
Matrix<T>& Matrix<T>::operator += (const Matrix<T>& mat){
    if(get_size() == 0){
        set_data(mat);
        return *this;
    }
    CHECK(equal_shape(mat));
    auto lamda = [](T* a, const T& b){ if(b != 0){*a += b;} };
    ParallelOperator po;
    po.parallel_mul2mul<T>(_data, get_size(), mat.data(), mat.get_size(), lamda);
    return *this;
}

template<class T>
Matrix<T> Matrix<T>::operator - (const T& value) const{
    auto lamda = [](T* a, const T& b){ if(b != 0){*a -= b;} };
    Matrix<T> mat;
    clone(mat);
    ParallelOperator po;
    po.parallel_mul2one<T>(mat.data(), mat.get_size(), value, lamda);
    return mat;
}

template<class T>
Matrix<T> Matrix<T>::operator - (const Matrix<T>& mat_a) const{
    CHECK(equal_shape(mat_a));
    auto lamda = [](T* a, const T& b){ if(b != 0){*a -= b;} };
    Matrix<T> mat;
    clone(mat);
    ParallelOperator po;
    po.parallel_mul2mul<T>(mat.data(), get_size(), mat_a.data(), mat_a.get_size(), lamda);
    return mat;
}

template<class T>
Matrix<T>& Matrix<T>::operator -= (const T& value){
    auto lamda = [](T* a, const T& b){ if(b != 0){*a -= b;} };
    ParallelOperator po;
    po.parallel_mul2one<T>(_data, get_size(), value, lamda);
	return *this;
}

template<class T>
Matrix<T>& Matrix<T>::operator -= (const Matrix<T>& mat){
    CHECK(equal_shape(mat));
    auto lamda = [](T* a, const T& b){ if(b != 0){*a -= b;} };
    ParallelOperator po;
    po.parallel_mul2mul<T>(_data, get_size(), mat.data(), mat.get_size(), lamda);
	return *this;
}

template<class T>
Matrix<T> Matrix<T>::operator * (const T& value) const{
    auto lamda = [](T* a, const T& b){ if(b != 1){*a *= b;} };
    Matrix<T> mat;
    clone(mat);
    ParallelOperator po;
    po.parallel_mul2one<T>(mat.data(), get_size(), value, lamda);
    return mat;
}

template<class T>
Matrix<T> Matrix<T>::operator * (const Matrix<T>& mat_a) const{
    CHECK(equal_shape(mat_a));
    auto lamda = [](T* a, const T& b){ if(b != 1){*a *= b;} };
    Matrix<T> mat;
    clone(mat);
    ParallelOperator po;
    po.parallel_mul2mul_repeat<T>(mat.data(), get_size(), mat.data(), mat.get_size(), lamda);
    return mat;
}

template<class T>
Matrix<T>& Matrix<T>::operator *= (const T& value){
    auto lamda = [](T* a, const T& b){ if(b != 1){*a *= b;} };
    ParallelOperator po;
    po.parallel_mul2one<T>(_data, get_size(), value, lamda);
	return *this;
}

template<class T>
Matrix<T>& Matrix<T>::operator *= (const Matrix<T>& mat){
    CHECK(equal_shape(mat));
    auto lamda = [](T* a, const T& b){ if(b != 1){*a *= b;} };
    ParallelOperator po;
    po.parallel_mul2mul<T>(_data, get_size(), mat.data(), mat.get_size(), lamda);
	return *this;
}

template<class T>
Matrix<T> Matrix<T>::operator / (const T& value) const{
    auto lamda = [](T* a, const T& b){ if(b != 1){*a /= b;} };
    Matrix<T> mat;
    clone(mat);
    ParallelOperator po;
    po.parallel_mul2one<T>(mat.data(), get_size(), value, lamda);
    return mat;
}

template<class T>
Matrix<T> Matrix<T>::operator / (const Matrix<T>& mat_a) const{
    CHECK(equal_shape(mat_a));
    auto lamda = [](T* a, const T& b){ if(b != 1){ *a /= b;} };
    Matrix<T> mat;
    clone(mat);
    ParallelOperator po;
    po.parallel_mul2mul<T>(mat.data(), mat.get_size(), mat_a.data(), mat_a.get_size(), lamda);
    return mat;
}

template<class T>
Matrix<T>& Matrix<T>::operator /= (const T& value){
    auto lamda = [](T* a, const T& b){ if(b != 1){*a /= b;} };
    ParallelOperator po;
    po.parallel_mul2one<T>(_data, get_size(), value, lamda);
	return *this;
}

template<class T>
Matrix<T>& Matrix<T>::operator /= (const Matrix<T>& mat){
    CHECK(equal_shape(mat));
    auto lamda = [](T* a, const T& b){ if(b != 1){*a /= b;} };
    ParallelOperator po;
    po.parallel_mul2mul<T>(_data, get_size(), mat.data(), mat.get_size(), lamda);
	return *this;
}

template class Matrix<int>;
template class Matrix<float>;
template class Matrix<double>;
}//namespace algebra
}//namespace abcdl
<|endoftext|>


<commit_before>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_PLAYGROUND_EVALUATION_ELLIPTIC_HH
#define DUNE_GDT_PLAYGROUND_EVALUATION_ELLIPTIC_HH

#include <dune/gdt/localevaluation/elliptic.hh>

namespace Dune {
namespace GDT {
namespace LocalEvaluation {

template< class DiffusionFactorType, class DiffusionTensorType >
class Elliptic
  : public LocalEvaluation::Codim0Interface< internal::EllipticTraits< DiffusionFactorType, DiffusionTensorType >, 2 >
{
public:
  typedef internal::EllipticTraits< DiffusionFactorType, DiffusionTensorType > Traits;

  Elliptic(const DiffusionFactorType& diffusion_factor,
           const DiffusionTensorType& diffusion_tensor)
    : diffusion_factor_(diffusion_factor)
    , diffusion_tensor_(diffusion_tensor)
  {}

  template< class EntityType >
  class LocalfunctionTuple
  {
    typedef typename DiffusionFactorType::LocalfunctionType LocalDiffusionFactorFunctionType;
    typedef typename DiffusionTensorType::LocalfunctionType LocalDiffusionTensorFunctionType;
  public:
    typedef std::tuple< std::shared_ptr< LocalDiffusionFactorFunctionType >
                      , std::shared_ptr< LocalDiffusionTensorFunctionType > > Type;
  }; // class LocalfunctionTuple

  template< class EntityType >
  typename LocalfunctionTuple< EntityType >::Type localFunctions(const EntityType& entity) const
  {
    return std::make_tuple(diffusion_factor_.local_function(entity),
                           diffusion_tensor_.local_function(entity));
  } // ... localFunctions(...)

  /**
   * \brief extracts the local functions and calls the correct order() method
   */
  template< class E, class D, int d, class R, int rT, int rCT, int rA, int rCA >
  size_t order(const typename LocalfunctionTuple< E >::Type& local_functions_tuple,
               const Stuff::LocalfunctionSetInterface< E, D, d, R, rT, rCT >& testBase,
               const Stuff::LocalfunctionSetInterface< E, D, d, R, rA, rCA >& ansatzBase) const
  {
    const auto local_diffusion_factor = std::get< 0 >(local_functions_tuple);
    const auto local_diffusion_tensor = std::get< 1 >(local_functions_tuple);
    return order(*local_diffusion_factor, *local_diffusion_tensor, testBase, ansatzBase);
  } // ... order(...)

  template< class E, class D, int d, class R, int rDF, int rCDF, int rDT, int rCDT, int rT, int rCT, int rA, int rCA >
  size_t order(const Stuff::LocalfunctionInterface< E, D, d, R, rDF, rCDF >& local_diffusion_factor,
               const Stuff::LocalfunctionInterface< E, D, d, R, rDT, rCDT >& local_diffusion_tensor,
               const Stuff::LocalfunctionSetInterface< E, D, d, R, rT, rCT >& testBase,
               const Stuff::LocalfunctionSetInterface< E, D, d, R, rA, rCA >& ansatzBase) const
  {
    return local_diffusion_factor.order()
        + local_diffusion_tensor.order()
        + std::max(ssize_t(testBase.order()) - 1, ssize_t(0))
        + std::max(ssize_t(ansatzBase.order()) - 1, ssize_t(0));
  } // ... order(...)

  /**
   * \brief extracts the local functions and calls the correct evaluate() method
   */
  template< class E, class D, int d, class R, int rT, int rCT, int rA, int rCA >
  void evaluate(const typename LocalfunctionTuple< E >::Type& local_functions_tuple,
                const Stuff::LocalfunctionSetInterface< E, D, d, R, rT, rCT >& testBase,
                const Stuff::LocalfunctionSetInterface< E, D, d, R, rA, rCA >& ansatzBase,
                const Dune::FieldVector< D, d >& localPoint,
                Dune::DynamicMatrix< R >& ret) const
  {
    const auto local_diffusion_factor = std::get< 0 >(local_functions_tuple);
    const auto local_diffusion_tensor = std::get< 1 >(local_functions_tuple);
    evaluate(*local_diffusion_factor, *local_diffusion_tensor, testBase, ansatzBase, localPoint, ret);
  }

  template< class E, class D, int d, class R, int rDF, int rCDF, int rDT, int rCDT, int rT, int rCT, int rA, int rCA >
  void evaluate(const Stuff::LocalfunctionInterface< E, D, d, R, rDF, rCDF >& /*local_diffusion_factor*/,
                const Stuff::LocalfunctionInterface< E, D, d, R, rDT, rCDT >& /*local_diffusion_tensor*/,
                const Stuff::LocalfunctionSetInterface< E, D, d, R, rT, rCT >& /*testBase*/,
                const Stuff::LocalfunctionSetInterface< E, D, d, R, rA, rCA >& /*ansatzBase*/,
                const Dune::FieldVector< D, d >& /*localPoint*/,
                Dune::DynamicMatrix< R >& /*ret*/) const
  {
    static_assert(Dune::AlwaysFalse< R >::value, "Not implemented for these dimensions!");
  }

  template< class E, class D, int d, class R, int r >
  void evaluate(const Stuff::LocalfunctionInterface< E, D, d, R, 1, 1 >& local_diffusion_factor,
                const Stuff::LocalfunctionInterface< E, D, d, R, 1, 1 >& local_diffusion_tensor,
                const Stuff::LocalfunctionSetInterface< E, D, d, R, r, 1 >& testBase,
                const Stuff::LocalfunctionSetInterface< E, D, d, R, r, 1 >& ansatzBase,
                const Dune::FieldVector< D, d >& localPoint,
                Dune::DynamicMatrix< R >& ret) const
  {
    typedef typename Stuff::LocalfunctionSetInterface< E, D, d, R, r, 1 >::JacobianRangeType JacobianRangeType;
    // evaluate local functions
    const auto local_diffusion_factor_value = local_diffusion_factor.evaluate(localPoint);
    const auto local_diffusion_tensor_value = local_diffusion_tensor.evaluate(localPoint);
    // evaluate test gradient
    const size_t rows = testBase.size();
    std::vector< JacobianRangeType > testGradients(rows, JacobianRangeType(0));
    testBase.jacobian(localPoint, testGradients);
    // evaluate ansatz gradient
    const size_t cols = ansatzBase.size();
    std::vector< JacobianRangeType > ansatzGradients(cols, JacobianRangeType(0));
    ansatzBase.jacobian(localPoint, ansatzGradients);
    // compute products
    assert(ret.rows() >= rows);
    assert(ret.cols() >= cols);
    for (size_t ii = 0; ii < rows; ++ii) {
      auto& retRow = ret[ii];
      for (size_t jj = 0; jj < cols; ++jj) {
        retRow[jj] = local_diffusion_factor_value * local_diffusion_tensor_value
                     * (ansatzGradients[jj][0] * testGradients[ii][0]);
      }
    }
  } // ... evaluate< ..., 1, 1 >(...)

  template< class E, class D, int d, class R >
  void evaluate(const Stuff::LocalfunctionInterface< E, D, d, R, 1, 1 >& local_diffusion_factor,
                const Stuff::LocalfunctionInterface< E, D, d, R, 2, 2 >& local_diffusion_tensor,
                const Stuff::LocalfunctionSetInterface< E, D, d, R, 1, 1 >& testBase,
                const Stuff::LocalfunctionSetInterface< E, D, d, R, 1, 1 >& ansatzBase,
                const Dune::FieldVector< D, d >& localPoint,
                Dune::DynamicMatrix< R >& ret) const
  {
    evaluate_matrix_valued_(local_diffusion_factor, local_diffusion_tensor, testBase, ansatzBase, localPoint, ret);
  }

  template< class E, class D, int d, class R >
  void evaluate(const Stuff::LocalfunctionInterface< E, D, d, R, 1, 1 >& local_diffusion_factor,
                const Stuff::LocalfunctionInterface< E, D, d, R, 3, 3 >& local_diffusion_tensor,
                const Stuff::LocalfunctionSetInterface< E, D, d, R, 1, 1 >& testBase,
                const Stuff::LocalfunctionSetInterface< E, D, d, R, 1, 1 >& ansatzBase,
                const Dune::FieldVector< D, d >& localPoint,
                Dune::DynamicMatrix< R >& ret) const
  {
    evaluate_matrix_valued_(local_diffusion_factor, local_diffusion_tensor, testBase, ansatzBase, localPoint, ret);
  }

private:
  template< class E, class D, int d, class R >
  void evaluate_matrix_valued_(const Stuff::LocalfunctionInterface< E, D, d, R, 1, 1 >& local_diffusion_factor,
                               const Stuff::LocalfunctionInterface< E, D, d, R, d, d >& local_diffusion_tensor,
                               const Stuff::LocalfunctionSetInterface< E, D, d, R, 1, 1 >& testBase,
                               const Stuff::LocalfunctionSetInterface< E, D, d, R, 1, 1 >& ansatzBase,
                               const Dune::FieldVector< D, d >& localPoint,
                               Dune::DynamicMatrix< R >& ret) const
  {
    typedef typename Stuff::LocalfunctionSetInterface< E, D, d, R, 1, 1 >::JacobianRangeType JacobianRangeType;
    // evaluate local functions
    const auto local_diffusion_factor_value = local_diffusion_factor.evaluate(localPoint);
    auto local_diffusion_tensor_value = local_diffusion_tensor.evaluate(localPoint);
    local_diffusion_tensor_value *= local_diffusion_factor_value[0];
    // evaluate test gradient
    const size_t rows = testBase.size();
    std::vector< JacobianRangeType > testGradients(rows, JacobianRangeType(0));
    testBase.jacobian(localPoint, testGradients);
    // evaluate ansatz gradient
    const size_t cols = ansatzBase.size();
    std::vector< JacobianRangeType > ansatzGradients(cols, JacobianRangeType(0));
    ansatzBase.jacobian(localPoint, ansatzGradients);
    // compute products
    assert(ret.rows() >= rows);
    assert(ret.cols() >= cols);
    FieldVector< D, d > product(0.0);
    for (size_t ii = 0; ii < rows; ++ii) {
      auto& retRow = ret[ii];
      for (size_t jj = 0; jj < cols; ++jj) {
        local_diffusion_tensor_value.mv(ansatzGradients[jj][0], product);
        retRow[jj] = product * testGradients[ii][0];
      }
    }
  } // ... evaluate_matrix_valued_(...)

  const DiffusionFactorType& diffusion_factor_;
  const DiffusionTensorType& diffusion_tensor_;
}; // class LocalElliptic

} // namespace Evaluation
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_PLAYGROUND_EVALUATION_ELLIPTIC_HH
<commit_msg>[playground.localevaluation.elliptic] adapt to interface changes<commit_after>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_PLAYGROUND_EVALUATION_ELLIPTIC_HH
#define DUNE_GDT_PLAYGROUND_EVALUATION_ELLIPTIC_HH

#include <dune/gdt/localevaluation/elliptic.hh>

namespace Dune {
namespace GDT {
namespace LocalEvaluation {

template< class DiffusionFactorImp, class DiffusionTensorImp >
class Elliptic
  : public LocalEvaluation::Codim0Interface< internal::EllipticTraits< DiffusionFactorImp, DiffusionTensorImp >, 2 >
{
public:
  typedef internal::EllipticTraits< DiffusionFactorImp, DiffusionTensorImp >  Traits;
  typedef typename Traits::LocalizableDiffusionFactorFunctionType             LocalizableDiffusionFactorFunctionType;
  typedef typename Traits::LocalizableDiffusionTensorFunctionType             LocalizableDiffusionTensorFunctionType;
  typedef typename Traits::LocalfunctionTupleType                             LocalfunctionTupleType;
  typedef typename Traits::EntityType                                         EntityType;
  typedef typename Traits::DomainFieldType                                    DomainFieldType;
  static const unsigned int dimDomain = Traits::dimDomain;

  Elliptic(const LocalizableDiffusionFactorFunctionType& diffusion_factor,
           const LocalizableDiffusionTensorFunctionType& diffusion_tensor)
    : diffusion_factor_(diffusion_factor)
    , diffusion_tensor_(diffusion_tensor)
  {}

  LocalfunctionTupleType localFunctions(const EntityType& entity) const
  {
    return std::make_tuple(diffusion_factor_.local_function(entity),
                           diffusion_tensor_.local_function(entity));
  } // ... localFunctions(...)

  /**
   * \brief extracts the local functions and calls the correct order() method
   */
  template< class R, int rT, int rCT, int rA, int rCA >
  size_t order(const LocalfunctionTupleType& local_functions_tuple,
               const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain
                                                     , R, rT, rCT >& testBase,
               const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain
                                                     , R, rA, rCA >& ansatzBase) const
  {
    const auto local_diffusion_factor = std::get< 0 >(local_functions_tuple);
    const auto local_diffusion_tensor = std::get< 1 >(local_functions_tuple);
    return order(*local_diffusion_factor, *local_diffusion_tensor, testBase, ansatzBase);
  } // ... order(...)

  /**
   * \brief extracts the local functions and calls the correct evaluate() method
   */
  template< class R, int rT, int rCT, int rA, int rCA >
  void evaluate(const LocalfunctionTupleType& local_functions_tuple,
                const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain
                                                      , R, rT, rCT >& testBase,
                const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain
                                                      , R, rA, rCA >& ansatzBase,
                const Dune::FieldVector< DomainFieldType, dimDomain >& localPoint,
                Dune::DynamicMatrix< R >& ret) const
  {
    const auto local_diffusion_factor = std::get< 0 >(local_functions_tuple);
    const auto local_diffusion_tensor = std::get< 1 >(local_functions_tuple);
    evaluate(*local_diffusion_factor, *local_diffusion_tensor, testBase, ansatzBase, localPoint, ret);
  }

private:
  template< class R, int rDF, int rCDF, int rDT, int rCDT, int rT, int rCT, int rA, int rCA >
  size_t order(const Stuff::LocalfunctionInterface< EntityType, DomainFieldType, dimDomain
                                                  , R, rDF, rCDF >& local_diffusion_factor,
               const Stuff::LocalfunctionInterface< EntityType, DomainFieldType, dimDomain
                                                  , R, rDT, rCDT >& local_diffusion_tensor,
               const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain
                                                     , R, rT, rCT >& testBase,
               const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain
                                                     , R, rA, rCA >& ansatzBase) const
  {
    return local_diffusion_factor.order()
        + local_diffusion_tensor.order()
        + std::max(ssize_t(testBase.order()) - 1, ssize_t(0))
        + std::max(ssize_t(ansatzBase.order()) - 1, ssize_t(0));
  } // ... order(...)

  template< class R, int rDF, int rCDF, int rDT, int rCDT, int rT, int rCT, int rA, int rCA >
  void evaluate(const Stuff::LocalfunctionInterface< EntityType, DomainFieldType, dimDomain
                                                   , R, rDF, rCDF >& /*local_diffusion_factor*/,
                const Stuff::LocalfunctionInterface< EntityType, DomainFieldType, dimDomain
                                                   , R, rDT, rCDT >& /*local_diffusion_tensor*/,
                const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain
                                                      , R, rT, rCT >& /*testBase*/,
                const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain
                                                      , R, rA, rCA >& /*ansatzBase*/,
                const Dune::FieldVector< DomainFieldType, dimDomain >& /*localPoint*/,
                Dune::DynamicMatrix< R >& /*ret*/) const
  {
    static_assert(Dune::AlwaysFalse< R >::value, "Not implemented for these dimensions!");
  } // ... evaluate< ... >(...)

  template< class R, int r >
  void evaluate(const Stuff::LocalfunctionInterface< EntityType, DomainFieldType, dimDomain
                                                   , R, 1, 1 >& local_diffusion_factor,
                const Stuff::LocalfunctionInterface< EntityType, DomainFieldType, dimDomain
                                                   , R, 1, 1 >& local_diffusion_tensor,
                const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain
                                                      , R, r, 1 >& testBase,
                const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain
                                                      , R, r, 1 >& ansatzBase,
                const Dune::FieldVector< DomainFieldType, dimDomain >& localPoint,
                Dune::DynamicMatrix< R >& ret) const
  {
    typedef typename Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain
                                                     , R, r, 1 >::JacobianRangeType   JacobianRangeType;
    // evaluate local functions
    const auto local_diffusion_factor_value = local_diffusion_factor.evaluate(localPoint);
    const auto local_diffusion_tensor_value = local_diffusion_tensor.evaluate(localPoint);
    // evaluate test gradient
    const size_t rows = testBase.size();
    std::vector< JacobianRangeType > testGradients(rows, JacobianRangeType(0));
    testBase.jacobian(localPoint, testGradients);
    // evaluate ansatz gradient
    const size_t cols = ansatzBase.size();
    std::vector< JacobianRangeType > ansatzGradients(cols, JacobianRangeType(0));
    ansatzBase.jacobian(localPoint, ansatzGradients);
    // compute products
    assert(ret.rows() >= rows);
    assert(ret.cols() >= cols);
    for (size_t ii = 0; ii < rows; ++ii) {
      auto& retRow = ret[ii];
      for (size_t jj = 0; jj < cols; ++jj) {
        retRow[jj] = local_diffusion_factor_value * local_diffusion_tensor_value
                     * (ansatzGradients[jj][0] * testGradients[ii][0]);
      }
    }
  } // ... evaluate< ..., 1, 1 >(...)

  template< class R >
  void evaluate(const Stuff::LocalfunctionInterface< EntityType, DomainFieldType, dimDomain
                                                   , R, 1, 1 >& local_diffusion_factor,
                const Stuff::LocalfunctionInterface< EntityType, DomainFieldType, dimDomain
                                                   , R, 2, 2 >& local_diffusion_tensor,
                const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain
                                                      , R, 1, 1 >& testBase,
                const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain
                                                      , R, 1, 1 >& ansatzBase,
                const Dune::FieldVector< DomainFieldType, dimDomain >& localPoint,
                Dune::DynamicMatrix< R >& ret) const
  {
    evaluate_matrix_valued_(local_diffusion_factor, local_diffusion_tensor, testBase, ansatzBase, localPoint, ret);
  }

  template< class R >
  void evaluate(const Stuff::LocalfunctionInterface< EntityType, DomainFieldType, dimDomain
                                                   , R, 1, 1 >& local_diffusion_factor,
                const Stuff::LocalfunctionInterface< EntityType, DomainFieldType, dimDomain
                                                   , R, 3, 3 >& local_diffusion_tensor,
                const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain
                                                      , R, 1, 1 >& testBase,
                const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain
                                                      , R, 1, 1 >& ansatzBase,
                const Dune::FieldVector< DomainFieldType, dimDomain >& localPoint,
                Dune::DynamicMatrix< R >& ret) const
  {
    evaluate_matrix_valued_(local_diffusion_factor, local_diffusion_tensor, testBase, ansatzBase, localPoint, ret);
  }

  template< class R >
  void evaluate_matrix_valued_(const Stuff::LocalfunctionInterface< EntityType, DomainFieldType, dimDomain
                                                                  , R, 1, 1 >& local_diffusion_factor,
                               const Stuff::LocalfunctionInterface< EntityType, DomainFieldType, dimDomain
                                                                  , R, dimDomain, dimDomain >& local_diffusion_tensor,
                               const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain
                                                                     , R, 1, 1 >& testBase,
                               const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain
                                                                     , R, 1, 1 >& ansatzBase,
                               const Dune::FieldVector< DomainFieldType, dimDomain >& localPoint,
                               Dune::DynamicMatrix< R >& ret) const
  {
    typedef typename Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain
                                                     , R, 1, 1 >::JacobianRangeType JacobianRangeType;
    // evaluate local functions
    const auto local_diffusion_factor_value = local_diffusion_factor.evaluate(localPoint);
    auto local_diffusion_tensor_value = local_diffusion_tensor.evaluate(localPoint);
    local_diffusion_tensor_value *= local_diffusion_factor_value[0];
    // evaluate test gradient
    const size_t rows = testBase.size();
    std::vector< JacobianRangeType > testGradients(rows, JacobianRangeType(0));
    testBase.jacobian(localPoint, testGradients);
    // evaluate ansatz gradient
    const size_t cols = ansatzBase.size();
    std::vector< JacobianRangeType > ansatzGradients(cols, JacobianRangeType(0));
    ansatzBase.jacobian(localPoint, ansatzGradients);
    // compute products
    assert(ret.rows() >= rows);
    assert(ret.cols() >= cols);
    FieldVector< DomainFieldType, dimDomain > product(0.0);
    for (size_t ii = 0; ii < rows; ++ii) {
      auto& retRow = ret[ii];
      for (size_t jj = 0; jj < cols; ++jj) {
        local_diffusion_tensor_value.mv(ansatzGradients[jj][0], product);
        retRow[jj] = product * testGradients[ii][0];
      }
    }
  } // ... evaluate_matrix_valued_(...)

  const LocalizableDiffusionFactorFunctionType& diffusion_factor_;
  const LocalizableDiffusionTensorFunctionType& diffusion_tensor_;
}; // class LocalElliptic

} // namespace Evaluation
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_PLAYGROUND_EVALUATION_ELLIPTIC_HH
<|endoftext|>


<commit_before><commit_msg>[FIXED] 打包时picture的offset没有乘scale系数<commit_after><|endoftext|>


<commit_before>// GUI.cpp
// 29. April 2017
// Created by:
// 		Bryan Burkhardt (bmburkhardt@alaska.edu)
// 		Alexander Eckert (aeckert@alaska.edu)
// 		Jeremiah Jacobson (jjjacobson2@alaska.edu)
// 		Jarye Murphy (@alaska.edu)
// 		Cameron Showalter (@alaska.edu)
//
// Source file for GUI class

#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include <iostream>

#include "../include/textureManager.hpp"
#include "../include/GUI.hpp"

GUI::GUI(std::shared_ptr<Music> music) : music(music) {
	std::cout << "ctor GUI\n";
	texmgr = std::make_unique<TextureManager>();
	loadTextures();
	window.create(sf::VideoMode(WINDOW_WIDTH, WINDOW_HEIGHT), "MusicPlayer",
		sf::Style::Titlebar | sf::Style::Close);
	setTextures();

}

bool GUI::clickInSprite(sf::Sprite s, int x , int y) {
	if (x > s.getGlobalBounds().left && x <
			(s.getGlobalBounds().left + s.getGlobalBounds().width) &&
			y > s.getGlobalBounds().top && y < (s.getGlobalBounds().top
			+ s.getGlobalBounds().height)) {
		return true;
	}
	return false;
}

std::string GUI::trimFilename(const std::string& str) {
  std::size_t found = str.find_last_of("/\\");
  return str.substr(found+1);
}

void GUI::draw() {
	window.clear(sf::Color::Green);

	// draw buttons
	window.draw(musicPlayerBG  );
	window.draw(playPauseButton);			//0
	window.draw(prevButton); 				//1
	window.draw(nextButton);				//2
	window.draw(muteButton); 				//3
	window.draw(increaseVolumeButton);		//4
	window.draw(decreaseVolumeButton);		//5

	window.draw(prevSong);
	window.draw(currentSong);
	window.draw(nextSong);
	window.draw(next2Song);
	window.draw(next3Song);
	window.draw(next4Song);
	window.display();

	return;
}

void GUI::loadTextures() {
	texmgr->loadTexture("musicPlayerBGTex", "../res/background/musicplayerbg.png");
	texmgr->loadTexture("playTex", "../res/icons/play.png");
	texmgr->loadTexture("pauseTex", "../res/icons/pause.png");
	texmgr->loadTexture("prevTex", "../res/icons/previous.png");
	texmgr->loadTexture("nextTex", "../res/icons/next.png");
	texmgr->loadTexture("decreaseVolumeTex", "../res/icons/volume_down.png");
	texmgr->loadTexture("increaseVolumeTex", "../res/icons/volume_up.png");
	texmgr->loadTexture("muteTex", "../res/icons/mute.png");
	texmgr->loadTexture("playTex2", "../res/icons/play2.png");
	texmgr->loadTexture("pauseTex2", "../res/icons/pause2.png");
	texmgr->loadTexture("prevTex2", "../res/icons/previous2.png");
	texmgr->loadTexture("nextTex2", "../res/icons/next2.png");
	texmgr->loadTexture("decreaseVolumeTex2", "../res/icons/volume_down2.png");
	texmgr->loadTexture("increaseVolumeTex2", "../res/icons/volume_up2.png");
	texmgr->loadTexture("muteTexv2", "../res/icons/mutev2.png");
	texmgr->loadTexture("muteTex2", "../res/icons/mute2.png");
	texmgr->loadTexture("muteTexv22", "../res/icons/mutev2-2.png");
	std::cout << "Textures loaded" << std::endl;
}

void GUI::setTextures() {
	spriteVec = {
		playPauseButton,			// 0
		prevButton, 				// 1
		nextButton, 				// 2
		muteButton, 				// 3
		decreaseVolumeButton, 		// 4
		increaseVolumeButton
	};

	// set textures
	musicPlayerBG.setTexture(this->texmgr->getRef("musicPlayerBGTex"));
	playPauseButton.setTexture(this->texmgr->getRef("pauseTex"));
	prevButton.setTexture(this->texmgr->getRef("prevTex"));
	nextButton.setTexture(this->texmgr->getRef("nextTex"));
	muteButton.setTexture(this->texmgr->getRef("muteTex"));
	decreaseVolumeButton.setTexture(this->texmgr->getRef("decreaseVolumeTex"));
	increaseVolumeButton.setTexture(this->texmgr->getRef("increaseVolumeTex"));

	// set positions
	playPauseButton.setPosition(120,210);
	prevButton.setPosition(30,210);
	nextButton.setPosition(210,210);
	decreaseVolumeButton.setPosition(120,120);
	muteButton.setPosition(30,120);
	increaseVolumeButton.setPosition(210,120);
}

void GUI::stylePlaylist() {
	if(!font.loadFromFile("../res/fonts/TravelingTypewriter.ttf"))
		std::cout << "Font couldn't be found" << std::endl;
	else
		std::cout << "Font was found" << std::endl;

	textVec = {
		prevSong,
		currentSong,
		nextSong,
		next2Song,
		next3Song,
		next4Song
	};

	int counter = 35;
	for(auto i=0; textVec.size()-1; ++i) {
		textVec[i].setFont(font);
		textVec[i].setCharacterSize(24);
		if(i == 1)
			textVec[i].setColor(sf::Color::Blue);
		else
			textVec[i].setColor(sf::Color::Black);
		textVec[i].setPosition(360,counter);
		counter += 25;
	}
}

void GUI::displayPlaylist() {
	if (music->songListIndex_ == 0) {
		prevSong.setString(trimFilename(music->songList_[music->songList_.size() - 1]));
	}
	else {
		prevSong.setString(trimFilename(music->songList_[music->songListIndex_ - 1]));
	}

	currentSong.setString(trimFilename(music->songList_[music->songListIndex_]));

	if (music->songListIndex_ == music->songList_.size() - 1) {
		nextSong.setString(trimFilename(music->songList_[0]));
	}
	else {
		nextSong.setString(trimFilename(music->songList_[music->songListIndex_ + 1]));
	}

	if (music->songListIndex_ == music->songList_.size() - 2) {
		next2Song.setString(trimFilename(music->songList_[0]));
	}
	else if (music->songListIndex_ == music->songList_.size() - 1) {
		next2Song.setString(trimFilename(music->songList_[1]));
	}
	else {
		next2Song.setString(trimFilename(music->songList_[music->songListIndex_ + 2]));
	}

	if (music->songListIndex_ == music->songList_.size() - 3) {
		next3Song.setString(trimFilename(music->songList_[0]));
	}
	else if (music->songListIndex_ == music->songList_.size() - 2) {
		next3Song.setString(trimFilename(music->songList_[1]));
	}
	else if (music->songListIndex_ == music->songList_.size() - 1) {
		next3Song.setString(trimFilename(music->songList_[2]));
	}
	else {
		next3Song.setString(trimFilename(music->songList_[music->songListIndex_ + 3]));
	}

	if (music->songListIndex_ == music->songList_.size() - 4) {
		next4Song.setString(trimFilename(music->songList_[0]));
	}
	else if (music->songListIndex_ == music->songList_.size() - 3) {
		next4Song.setString(trimFilename(music->songList_[1]));
	}
	else if (music->songListIndex_ == music->songList_.size() - 2) {
		next4Song.setString(trimFilename(music->songList_[2]));
	}
	else if (music->songListIndex_ == music->songList_.size() - 1) {
		next4Song.setString(trimFilename(music->songList_[3]));
	}
	else {
		next4Song.setString(trimFilename(music->songList_[music->songListIndex_ + 4]));
	}
}

void GUI::update() {
	//stylePlaylist();
	displayPlaylist();
	return;
}<commit_msg>set font in ctor<commit_after>// GUI.cpp
// 29. April 2017
// Created by:
// 		Bryan Burkhardt (bmburkhardt@alaska.edu)
// 		Alexander Eckert (aeckert@alaska.edu)
// 		Jeremiah Jacobson (jjjacobson2@alaska.edu)
// 		Jarye Murphy (@alaska.edu)
// 		Cameron Showalter (@alaska.edu)
//
// Source file for GUI class

#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include <iostream>

#include "../include/textureManager.hpp"
#include "../include/GUI.hpp"

GUI::GUI(std::shared_ptr<Music> music) : music(music) {
	std::cout << "ctor GUI\n";
	texmgr = std::make_unique<TextureManager>();
	loadTextures();
	window.create(sf::VideoMode(WINDOW_WIDTH, WINDOW_HEIGHT), "MusicPlayer",
		sf::Style::Titlebar | sf::Style::Close);
	window.setFramerateLimit(60);
	setTextures();
	if(!font.loadFromFile("../res/fonts/TravelingTypewriter.ttf"))
		std::cout << "Font couldn't be found" << std::endl;
	else
		std::cout << "Font was found" << std::endl;
}

bool GUI::clickInSprite(sf::Sprite s, int x , int y) {
	if (x > s.getGlobalBounds().left && x <
			(s.getGlobalBounds().left + s.getGlobalBounds().width) &&
			y > s.getGlobalBounds().top && y < (s.getGlobalBounds().top
			+ s.getGlobalBounds().height)) {
		return true;
	}
	return false;
}

std::string GUI::trimFilename(const std::string& str) {
  std::size_t found = str.find_last_of("/\\");
  return str.substr(found+1);
}

void GUI::draw() {
	window.clear(sf::Color::Green);

	// draw buttons
	window.draw(musicPlayerBG  );
	window.draw(playPauseButton);			//0
	window.draw(prevButton); 				//1
	window.draw(nextButton);				//2
	window.draw(muteButton); 				//3
	window.draw(increaseVolumeButton);		//4
	window.draw(decreaseVolumeButton);		//5

	window.draw(prevSong);
	window.draw(currentSong);
	window.draw(nextSong);
	window.draw(next2Song);
	window.draw(next3Song);
	window.draw(next4Song);
	window.display();

	return;
}

void GUI::loadTextures() {
	texmgr->loadTexture("musicPlayerBGTex", "../res/background/musicplayerbg.png");
	texmgr->loadTexture("playTex", "../res/icons/play.png");
	texmgr->loadTexture("pauseTex", "../res/icons/pause.png");
	texmgr->loadTexture("prevTex", "../res/icons/previous.png");
	texmgr->loadTexture("nextTex", "../res/icons/next.png");
	texmgr->loadTexture("decreaseVolumeTex", "../res/icons/volume_down.png");
	texmgr->loadTexture("increaseVolumeTex", "../res/icons/volume_up.png");
	texmgr->loadTexture("muteTex", "../res/icons/mute.png");
	texmgr->loadTexture("playTex2", "../res/icons/play2.png");
	texmgr->loadTexture("pauseTex2", "../res/icons/pause2.png");
	texmgr->loadTexture("prevTex2", "../res/icons/previous2.png");
	texmgr->loadTexture("nextTex2", "../res/icons/next2.png");
	texmgr->loadTexture("decreaseVolumeTex2", "../res/icons/volume_down2.png");
	texmgr->loadTexture("increaseVolumeTex2", "../res/icons/volume_up2.png");
	texmgr->loadTexture("muteTexv2", "../res/icons/mutev2.png");
	texmgr->loadTexture("muteTex2", "../res/icons/mute2.png");
	texmgr->loadTexture("muteTexv22", "../res/icons/mutev2-2.png");
	std::cout << "Textures loaded" << std::endl;
}

void GUI::setTextures() {
	spriteVec = {
		playPauseButton,			// 0
		prevButton, 				// 1
		nextButton, 				// 2
		muteButton, 				// 3
		decreaseVolumeButton, 		// 4
		increaseVolumeButton
	};

	// set textures
	musicPlayerBG.setTexture(this->texmgr->getRef("musicPlayerBGTex"));
	playPauseButton.setTexture(this->texmgr->getRef("pauseTex"));
	prevButton.setTexture(this->texmgr->getRef("prevTex"));
	nextButton.setTexture(this->texmgr->getRef("nextTex"));
	muteButton.setTexture(this->texmgr->getRef("muteTex"));
	decreaseVolumeButton.setTexture(this->texmgr->getRef("decreaseVolumeTex"));
	increaseVolumeButton.setTexture(this->texmgr->getRef("increaseVolumeTex"));

	// set positions
	playPauseButton.setPosition(120,210);
	prevButton.setPosition(30,210);
	nextButton.setPosition(210,210);
	decreaseVolumeButton.setPosition(120,120);
	muteButton.setPosition(30,120);
	increaseVolumeButton.setPosition(210,120);
}

void GUI::stylePlaylist() {
	textVec = {
		prevSong,
		currentSong,
		nextSong,
		next2Song,
		next3Song,
		next4Song
	};

	int counter = 35;
	for(auto i=0; i <= textVec.size()-1; ++i) {
		textVec[i].setFont(font);
		textVec[i].setCharacterSize(24);
		if(i == 1)
			textVec[i].setColor(sf::Color::Blue);
		else
			textVec[i].setColor(sf::Color::Black);
		textVec[i].setPosition(360,counter);
		counter += 25;
	}
}

void GUI::displayPlaylist() {
	if (music->songListIndex_ == 0) {
		prevSong.setString(trimFilename(music->songList_[music->songList_.size() - 1]));
	}
	else {
		prevSong.setString(trimFilename(music->songList_[music->songListIndex_ - 1]));
	}

	currentSong.setString(trimFilename(music->songList_[music->songListIndex_]));

	if (music->songListIndex_ == music->songList_.size() - 1) {
		nextSong.setString(trimFilename(music->songList_[0]));
	}
	else {
		nextSong.setString(trimFilename(music->songList_[music->songListIndex_ + 1]));
	}

	if (music->songListIndex_ == music->songList_.size() - 2) {
		next2Song.setString(trimFilename(music->songList_[0]));
	}
	else if (music->songListIndex_ == music->songList_.size() - 1) {
		next2Song.setString(trimFilename(music->songList_[1]));
	}
	else {
		next2Song.setString(trimFilename(music->songList_[music->songListIndex_ + 2]));
	}

	if (music->songListIndex_ == music->songList_.size() - 3) {
		next3Song.setString(trimFilename(music->songList_[0]));
	}
	else if (music->songListIndex_ == music->songList_.size() - 2) {
		next3Song.setString(trimFilename(music->songList_[1]));
	}
	else if (music->songListIndex_ == music->songList_.size() - 1) {
		next3Song.setString(trimFilename(music->songList_[2]));
	}
	else {
		next3Song.setString(trimFilename(music->songList_[music->songListIndex_ + 3]));
	}

	if (music->songListIndex_ == music->songList_.size() - 4) {
		next4Song.setString(trimFilename(music->songList_[0]));
	}
	else if (music->songListIndex_ == music->songList_.size() - 3) {
		next4Song.setString(trimFilename(music->songList_[1]));
	}
	else if (music->songListIndex_ == music->songList_.size() - 2) {
		next4Song.setString(trimFilename(music->songList_[2]));
	}
	else if (music->songListIndex_ == music->songList_.size() - 1) {
		next4Song.setString(trimFilename(music->songList_[3]));
	}
	else {
		next4Song.setString(trimFilename(music->songList_[music->songListIndex_ + 4]));
	}
}

void GUI::update() {
	stylePlaylist();
	displayPlaylist();
	return;
}<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
//  VoxelTest Main.cc
//------------------------------------------------------------------------------
#include "Pre.h"
#include "Core/Main.h"
#include "Gfx/Gfx.h"
#include "Input/Input.h"
#include "Dbg/Dbg.h"
#include "Core/Time/Clock.h"
#include "shaders.h"
#include "GeomPool.h"
#include "GeomMesher.h"
#include "VoxelGenerator.h"
#include "VisTree.h"
#include "Camera.h"
#include "glm/gtc/matrix_transform.hpp"

using namespace Oryol;

const int MaxChunksGeneratedPerFrame = 1;

class VoxelTest : public App {
public:
    AppState::Code OnInit();
    AppState::Code OnRunning();
    AppState::Code OnCleanup();

    void init_blocks(int frameIndex);
    int bake_geom(const GeomMesher::Result& meshResult);
    void handle_input();

    int frameIndex = 0;
    int lastFrameIndex = -1;
    glm::vec3 lightDir;
    ClearState clearState;

    Camera camera;
    GeomPool geomPool;
    GeomMesher geomMesher;
    VoxelGenerator voxelGenerator;
    VisTree visTree;
};
OryolMain(VoxelTest);

//------------------------------------------------------------------------------
AppState::Code
VoxelTest::OnInit() {
    this->clearState = ClearState::ClearAll(glm::vec4(0.2f, 0.2f, 0.5f, 1.0f), 1.0f, 0);
    auto gfxSetup = GfxSetup::WindowMSAA4(800, 600, "Oryol Voxel Test");
    gfxSetup.SetPoolSize(GfxResourceType::Pipeline, 1024);
    gfxSetup.SetPoolSize(GfxResourceType::Mesh, 1024);
    gfxSetup.ClearHint = this->clearState;
    Gfx::Setup(gfxSetup);
    Input::Setup();
    Input::SetMousePointerLockHandler([](const InputEvent& event) -> PointerLockMode::Code {
        // switch pointer-lock on/off on left-mouse-button
        if ((event.Button == MouseButton::Left) || (event.Button == MouseButton::Right)) {
            if (event.Type == InputEvent::MouseButtonDown) {
                return PointerLockMode::Enable;
            }
            else if (event.Type == InputEvent::MouseButtonUp) {
                return PointerLockMode::Disable;
            }
        }
        return PointerLockMode::DontCare;
    });
    Dbg::Setup();

    const float fbWidth = (const float) Gfx::DisplayAttrs().FramebufferWidth;
    const float fbHeight = (const float) Gfx::DisplayAttrs().FramebufferHeight;
    this->camera.Setup(glm::vec3(4096, 128, 4096), glm::radians(45.0f), fbWidth, fbHeight, 0.1f, 10000.0f);
    this->lightDir = glm::normalize(glm::vec3(0.5f, 1.0f, 0.25f));

    this->geomPool.Setup(gfxSetup);
    this->geomMesher.Setup();
    // use a fixed display width, otherwise the geom pool could
    // run out of items at high resolutions
    const float displayWidth = 800;
    this->visTree.Setup(displayWidth, glm::radians(45.0f));

    return App::OnInit();
}

//------------------------------------------------------------------------------
int
VoxelTest::bake_geom(const GeomMesher::Result& meshResult) {
    if (meshResult.NumQuads > 0) {
        int geomIndex = this->geomPool.Alloc();
        auto& geom = this->geomPool.Geoms[geomIndex];
        Gfx::UpdateVertices(geom.Mesh, meshResult.Vertices, meshResult.NumBytes);
        geom.NumQuads = meshResult.NumQuads;
        geom.VSParams.Model = glm::mat4();
        geom.VSParams.LightDir = this->lightDir;
        geom.VSParams.Scale = meshResult.Scale;
        geom.VSParams.Translate = meshResult.Translate;
        geom.VSParams.TexTranslate = meshResult.TexTranslate;
        return geomIndex;
    }
    else {
        return VisNode::EmptyGeom;
    }
}

//------------------------------------------------------------------------------
AppState::Code
VoxelTest::OnRunning() {
    this->frameIndex++;
    this->handle_input();

    Gfx::ApplyDefaultRenderTarget(this->clearState);

    // traverse the vis-tree
    this->visTree.Traverse(this->camera);
    // free any geoms to be freed
    while (!this->visTree.freeGeoms.Empty()) {
        int geom = this->visTree.freeGeoms.PopBack();
        this->geomPool.Free(geom);
    }
    // init new geoms
    if (!this->visTree.geomGenJobs.Empty()) {
        int numProcessedJobs = 0;
        while ((numProcessedJobs < MaxChunksGeneratedPerFrame) && !this->visTree.geomGenJobs.Empty()) {
            numProcessedJobs++;
            int16_t     geoms[VisNode::NumGeoms];
            int numGeoms = 0;
            VisTree::GeomGenJob job = this->visTree.geomGenJobs.PopBack();
            Volume vol = this->voxelGenerator.GenSimplex(job.Bounds);
            GeomMesher::Result meshResult;
            this->geomMesher.Start();
            this->geomMesher.StartVolume(vol);
            do {
                meshResult = this->geomMesher.Meshify();
                meshResult.Scale = job.Scale;
                meshResult.Translate = job.Translate;
                if (meshResult.BufferFull) {
                    int geom = this->bake_geom(meshResult);
                    o_assert(numGeoms < VisNode::NumGeoms);
                    geoms[numGeoms++] = geom;
                }
            }
            while (!meshResult.VolumeDone);
            int geom = this->bake_geom(meshResult);
            o_assert(numGeoms < VisNode::NumGeoms);
            geoms[numGeoms++] = geom;
            this->visTree.ApplyGeoms(job.NodeIndex, geoms, numGeoms);
        }
    }

    // render visible geoms
    const int numDrawNodes = this->visTree.drawNodes.Size();
    int numQuads = 0;
    int numGeoms = 0;
    DrawState drawState;
    drawState.Mesh[0] = this->geomPool.IndexMesh;
    drawState.Pipeline = this->geomPool.Pipeline;
    for (int i = 0; i < numDrawNodes; i++) {
        const VisNode& node = this->visTree.NodeAt(this->visTree.drawNodes[i]);
        for (int geomIndex = 0; geomIndex < VisNode::NumGeoms; geomIndex++) {
            if (node.geoms[geomIndex] >= 0) {
                auto& geom = this->geomPool.Geoms[node.geoms[geomIndex]];
                drawState.Mesh[1] = geom.Mesh;
                geom.VSParams.ModelViewProjection = this->camera.ViewProj;
                Gfx::ApplyDrawState(drawState);
                Gfx::ApplyUniformBlock(geom.VSParams);
                Gfx::Draw(PrimitiveGroup(0, geom.NumQuads*6));
                numQuads += geom.NumQuads;
                numGeoms++;
            }
        }
    }
    Dbg::PrintF("\n\r"
                " Desktop:  LMB+Mouse or AWSD to move, RMB+Mouse to look around\n\r"
                " Mobile:   touch+pan to fly\n\n\r"
                " draws: %d\n\r"
                " tris: %d\n\r"
                " avail geoms: %d\n\r"
                " avail nodes: %d\n\r"
                " pending chunks: %d\n\r",
                numGeoms, numQuads*2,
                this->geomPool.freeGeoms.Size(),
                this->visTree.freeNodes.Size(),
                this->visTree.geomGenJobs.Size());
    Dbg::DrawTextBuffer();
    Gfx::CommitFrame();

    return Gfx::QuitRequested() ? AppState::Cleanup : AppState::Running;
}

//------------------------------------------------------------------------------
AppState::Code
VoxelTest::OnCleanup() {
    this->visTree.Discard();
    this->geomMesher.Discard();
    this->geomPool.Discard();
    Dbg::Discard();
    Input::Discard();
    Gfx::Discard();
    return App::OnCleanup();
}

//------------------------------------------------------------------------------
void
VoxelTest::handle_input() {
    glm::vec3 move;
    glm::vec2 rot;
    const float vel = 0.75f;
    if (Input::KeyboardAttached()) {
        if (Input::KeyPressed(Key::W) || Input::KeyPressed(Key::Up)) {
            move.z -= vel;
        }
        if (Input::KeyPressed(Key::S) || Input::KeyPressed(Key::Down)) {
            move.z += vel;
        }
        if (Input::KeyPressed(Key::A) || Input::KeyPressed(Key::Left)) {
            move.x -= vel;
        }
        if (Input::KeyPressed(Key::D) || Input::KeyPressed(Key::Right)) {
            move.x += vel;
        }
    }
    if (Input::MouseAttached) {
        if (Input::MouseButtonPressed(MouseButton::Left)) {
            move.z -= vel;
        }
        if (Input::MouseButtonPressed(MouseButton::Left) || Input::MouseButtonPressed(MouseButton::Right)) {
            rot = Input::MouseMovement() * glm::vec2(-0.01f, -0.007f);
        }
    }
    if (Input::TouchpadAttached) {
        if (Input::TouchPanning()) {
            move.z -= vel;
            rot = Input::TouchMovement(0) * glm::vec2(-0.01f, 0.01f);
        }
    }
    this->camera.MoveRotate(move, rot);
}
<commit_msg>More Input API tweaks<commit_after>//------------------------------------------------------------------------------
//  VoxelTest Main.cc
//------------------------------------------------------------------------------
#include "Pre.h"
#include "Core/Main.h"
#include "Gfx/Gfx.h"
#include "Input/Input.h"
#include "Dbg/Dbg.h"
#include "Core/Time/Clock.h"
#include "shaders.h"
#include "GeomPool.h"
#include "GeomMesher.h"
#include "VoxelGenerator.h"
#include "VisTree.h"
#include "Camera.h"
#include "glm/gtc/matrix_transform.hpp"

using namespace Oryol;

const int MaxChunksGeneratedPerFrame = 1;

class VoxelTest : public App {
public:
    AppState::Code OnInit();
    AppState::Code OnRunning();
    AppState::Code OnCleanup();

    void init_blocks(int frameIndex);
    int bake_geom(const GeomMesher::Result& meshResult);
    void handle_input();

    int frameIndex = 0;
    int lastFrameIndex = -1;
    glm::vec3 lightDir;
    ClearState clearState;

    Camera camera;
    GeomPool geomPool;
    GeomMesher geomMesher;
    VoxelGenerator voxelGenerator;
    VisTree visTree;
};
OryolMain(VoxelTest);

//------------------------------------------------------------------------------
AppState::Code
VoxelTest::OnInit() {
    this->clearState = ClearState::ClearAll(glm::vec4(0.2f, 0.2f, 0.5f, 1.0f), 1.0f, 0);
    auto gfxSetup = GfxSetup::WindowMSAA4(800, 600, "Oryol Voxel Test");
    gfxSetup.SetPoolSize(GfxResourceType::Pipeline, 1024);
    gfxSetup.SetPoolSize(GfxResourceType::Mesh, 1024);
    gfxSetup.ClearHint = this->clearState;
    Gfx::Setup(gfxSetup);
    Input::Setup();
    Input::SetPointerLockHandler([](const InputEvent& event) -> PointerLockMode::Code {
        // switch pointer-lock on/off on left-mouse-button
        if ((event.Button == MouseButton::Left) || (event.Button == MouseButton::Right)) {
            if (event.Type == InputEvent::MouseButtonDown) {
                return PointerLockMode::Enable;
            }
            else if (event.Type == InputEvent::MouseButtonUp) {
                return PointerLockMode::Disable;
            }
        }
        return PointerLockMode::DontCare;
    });
    Dbg::Setup();

    const float fbWidth = (const float) Gfx::DisplayAttrs().FramebufferWidth;
    const float fbHeight = (const float) Gfx::DisplayAttrs().FramebufferHeight;
    this->camera.Setup(glm::vec3(4096, 128, 4096), glm::radians(45.0f), fbWidth, fbHeight, 0.1f, 10000.0f);
    this->lightDir = glm::normalize(glm::vec3(0.5f, 1.0f, 0.25f));

    this->geomPool.Setup(gfxSetup);
    this->geomMesher.Setup();
    // use a fixed display width, otherwise the geom pool could
    // run out of items at high resolutions
    const float displayWidth = 800;
    this->visTree.Setup(displayWidth, glm::radians(45.0f));

    return App::OnInit();
}

//------------------------------------------------------------------------------
int
VoxelTest::bake_geom(const GeomMesher::Result& meshResult) {
    if (meshResult.NumQuads > 0) {
        int geomIndex = this->geomPool.Alloc();
        auto& geom = this->geomPool.Geoms[geomIndex];
        Gfx::UpdateVertices(geom.Mesh, meshResult.Vertices, meshResult.NumBytes);
        geom.NumQuads = meshResult.NumQuads;
        geom.VSParams.Model = glm::mat4();
        geom.VSParams.LightDir = this->lightDir;
        geom.VSParams.Scale = meshResult.Scale;
        geom.VSParams.Translate = meshResult.Translate;
        geom.VSParams.TexTranslate = meshResult.TexTranslate;
        return geomIndex;
    }
    else {
        return VisNode::EmptyGeom;
    }
}

//------------------------------------------------------------------------------
AppState::Code
VoxelTest::OnRunning() {
    this->frameIndex++;
    this->handle_input();

    Gfx::ApplyDefaultRenderTarget(this->clearState);

    // traverse the vis-tree
    this->visTree.Traverse(this->camera);
    // free any geoms to be freed
    while (!this->visTree.freeGeoms.Empty()) {
        int geom = this->visTree.freeGeoms.PopBack();
        this->geomPool.Free(geom);
    }
    // init new geoms
    if (!this->visTree.geomGenJobs.Empty()) {
        int numProcessedJobs = 0;
        while ((numProcessedJobs < MaxChunksGeneratedPerFrame) && !this->visTree.geomGenJobs.Empty()) {
            numProcessedJobs++;
            int16_t     geoms[VisNode::NumGeoms];
            int numGeoms = 0;
            VisTree::GeomGenJob job = this->visTree.geomGenJobs.PopBack();
            Volume vol = this->voxelGenerator.GenSimplex(job.Bounds);
            GeomMesher::Result meshResult;
            this->geomMesher.Start();
            this->geomMesher.StartVolume(vol);
            do {
                meshResult = this->geomMesher.Meshify();
                meshResult.Scale = job.Scale;
                meshResult.Translate = job.Translate;
                if (meshResult.BufferFull) {
                    int geom = this->bake_geom(meshResult);
                    o_assert(numGeoms < VisNode::NumGeoms);
                    geoms[numGeoms++] = geom;
                }
            }
            while (!meshResult.VolumeDone);
            int geom = this->bake_geom(meshResult);
            o_assert(numGeoms < VisNode::NumGeoms);
            geoms[numGeoms++] = geom;
            this->visTree.ApplyGeoms(job.NodeIndex, geoms, numGeoms);
        }
    }

    // render visible geoms
    const int numDrawNodes = this->visTree.drawNodes.Size();
    int numQuads = 0;
    int numGeoms = 0;
    DrawState drawState;
    drawState.Mesh[0] = this->geomPool.IndexMesh;
    drawState.Pipeline = this->geomPool.Pipeline;
    for (int i = 0; i < numDrawNodes; i++) {
        const VisNode& node = this->visTree.NodeAt(this->visTree.drawNodes[i]);
        for (int geomIndex = 0; geomIndex < VisNode::NumGeoms; geomIndex++) {
            if (node.geoms[geomIndex] >= 0) {
                auto& geom = this->geomPool.Geoms[node.geoms[geomIndex]];
                drawState.Mesh[1] = geom.Mesh;
                geom.VSParams.ModelViewProjection = this->camera.ViewProj;
                Gfx::ApplyDrawState(drawState);
                Gfx::ApplyUniformBlock(geom.VSParams);
                Gfx::Draw(PrimitiveGroup(0, geom.NumQuads*6));
                numQuads += geom.NumQuads;
                numGeoms++;
            }
        }
    }
    Dbg::PrintF("\n\r"
                " Desktop:  LMB+Mouse or AWSD to move, RMB+Mouse to look around\n\r"
                " Mobile:   touch+pan to fly\n\n\r"
                " draws: %d\n\r"
                " tris: %d\n\r"
                " avail geoms: %d\n\r"
                " avail nodes: %d\n\r"
                " pending chunks: %d\n\r",
                numGeoms, numQuads*2,
                this->geomPool.freeGeoms.Size(),
                this->visTree.freeNodes.Size(),
                this->visTree.geomGenJobs.Size());
    Dbg::DrawTextBuffer();
    Gfx::CommitFrame();

    return Gfx::QuitRequested() ? AppState::Cleanup : AppState::Running;
}

//------------------------------------------------------------------------------
AppState::Code
VoxelTest::OnCleanup() {
    this->visTree.Discard();
    this->geomMesher.Discard();
    this->geomPool.Discard();
    Dbg::Discard();
    Input::Discard();
    Gfx::Discard();
    return App::OnCleanup();
}

//------------------------------------------------------------------------------
void
VoxelTest::handle_input() {
    glm::vec3 move;
    glm::vec2 rot;
    const float vel = 0.75f;
    if (Input::KeyboardAttached()) {
        if (Input::KeyPressed(Key::W) || Input::KeyPressed(Key::Up)) {
            move.z -= vel;
        }
        if (Input::KeyPressed(Key::S) || Input::KeyPressed(Key::Down)) {
            move.z += vel;
        }
        if (Input::KeyPressed(Key::A) || Input::KeyPressed(Key::Left)) {
            move.x -= vel;
        }
        if (Input::KeyPressed(Key::D) || Input::KeyPressed(Key::Right)) {
            move.x += vel;
        }
    }
    if (Input::MouseAttached) {
        if (Input::MouseButtonPressed(MouseButton::Left)) {
            move.z -= vel;
        }
        if (Input::MouseButtonPressed(MouseButton::Left) || Input::MouseButtonPressed(MouseButton::Right)) {
            rot = Input::MouseMovement() * glm::vec2(-0.01f, -0.007f);
        }
    }
    if (Input::TouchpadAttached) {
        if (Input::TouchPanning()) {
            move.z -= vel;
            rot = Input::TouchMovement(0) * glm::vec2(-0.01f, 0.01f);
        }
    }
    this->camera.MoveRotate(move, rot);
}
<|endoftext|>