<commit_before>#include "widget.h"

void MainWindow::CreateTrayIcon()
{
    QMenu* pTrayIconMenu = new QMenu(this);
    pTrayIconMenu->addAction(m_pOpenAction);
    pTrayIconMenu->addSeparator();
    pTrayIconMenu->addAction(m_pPostponeAction);
    pTrayIconMenu->addSeparator();
    pTrayIconMenu->addAction(m_pQuitAction);

    if(m_pTrayIcon)
    {
        m_pTrayIcon->setContextMenu(pTrayIconMenu);
    }
}

void MainWindow::SetTrayIcon(QString strIcon)
{
    if(strIcon != m_strSetTrayIcon && m_pTrayIcon)
    {
        QIcon icon(strIcon);
        m_pTrayIcon->setIcon(icon);
        m_pTrayIcon->setVisible(true);

        m_strSetTrayIcon = strIcon;
    }
}

void MainWindow::LoadSettings()
{
    m_pAppSettings = new QSettings(QCoreApplication::organizationName(), QCoreApplication::applicationName(), this);
    qDebug() << QCoreApplication::organizationName() << QCoreApplication::applicationName();

    UserTimeSettings::SetWorkTime_s(m_pAppSettings->value("work_time", UserTimeSettings::WorkTime_s()).toInt());
    UserTimeSettings::SetRestTime_s(m_pAppSettings->value("rest_time", UserTimeSettings::RestTime_s()).toInt());
    UserTimeSettings::SetToleranceTime_s(m_pAppSettings->value("tolerance_time", UserTimeSettings::ToleranceTime_s()).toInt());

    m_pOnTopAction->setChecked(m_pAppSettings->value("always_on_top", false).toBool());
    SetOnTop(m_pOnTopAction->isChecked());

    m_pOnStartUpAction->setChecked(m_pAppSettings->value("run_on_startup", false).toBool());
}

void MainWindow::CreateLayout()
{
    QVBoxLayout* pTimeLayout = new QVBoxLayout;

    // work spin box
    QHBoxLayout* pWorkLayout = new QHBoxLayout;
    QLabel* pWorkLabel = new QLabel(tr("Work time [mins]"));
    QSpinBox* pSpinWorkTime_s = new QSpinBox(this); // TODO - má tu být this? Nemá tu být některý child?
    pSpinWorkTime_s->setValue(UserTimeSettings::WorkTime_s() / 60);
    pSpinWorkTime_s->setMaximum(999);
    connect(pSpinWorkTime_s, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), [&](const int &nNewValue) {
        UserTimeSettings::SetWorkTime_s(nNewValue * 60);
        m_pAppSettings->setValue("work_time", UserTimeSettings::WorkTime_s());
    });
    pWorkLayout->addWidget(pWorkLabel);
    pWorkLayout->addWidget(pSpinWorkTime_s);

    // rest spin box
    QHBoxLayout* pRestLayout = new QHBoxLayout;
    QLabel* pRestLabel = new QLabel(tr("Rest time [mins]"));
    QSpinBox* pSpinRestTime_s = new QSpinBox(this);
    pSpinRestTime_s->setValue(UserTimeSettings::RestTime_s() / 60);
    pSpinRestTime_s->setMaximum(999);
    connect(pSpinRestTime_s, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), [&](const int &nNewValue) {
       UserTimeSettings::SetRestTime_s(nNewValue * 60);
       m_pAppSettings->setValue("rest_time", UserTimeSettings::RestTime_s());
    });
    pRestLayout->addWidget(pRestLabel);
    pRestLayout->addWidget(pSpinRestTime_s);

    // tolerance spin box
    QHBoxLayout* pToleranceLayout = new QHBoxLayout;
    QLabel* pToleranceLabel = new QLabel(tr("Tolerance time [s]"));
    QSpinBox* pSpinToleranceTime_s = new QSpinBox(this);
    pSpinToleranceTime_s->setValue(UserTimeSettings::ToleranceTime_s());
    pSpinToleranceTime_s->setMaximum(999);
    connect(pSpinToleranceTime_s, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), [&](const int &nNewValue) {
       UserTimeSettings::SetToleranceTime_s(nNewValue);
       m_pAppSettings->setValue("tolerance_time", UserTimeSettings::ToleranceTime_s());

    });
    pToleranceLayout->addWidget(pToleranceLabel);
    pToleranceLayout->addWidget(pSpinToleranceTime_s);

    // add all to vertical layout
    pTimeLayout->addLayout(pWorkLayout);
    pTimeLayout->addLayout(pRestLayout);
    pTimeLayout->addLayout(pToleranceLayout);

    // add label with info
    m_pLabel = new QLabel;

    QVBoxLayout* pMainLayout = new QVBoxLayout;
    pMainLayout->addLayout(pTimeLayout);

    m_pPassedToleranceBar = new QProgressBar(this);
    m_pPassedToleranceBar->setMaximum(0);
    m_pPassedToleranceBar->setMaximum(UserTimeSettings::ToleranceTime_s() * 1000);
    m_pPassedToleranceBar->setTextVisible(false);

    pMainLayout->addWidget(m_pPassedToleranceBar);
    pMainLayout->addWidget(m_pLabel);

    QWidget* pWidget = new QWidget(this);
    pWidget->setLayout(pMainLayout);
    this->setCentralWidget(pWidget);
}

void MainWindow::CreateActions()
{
    m_pOpenAction = new QAction(tr("&Open"), this);
    connect(m_pOpenAction, &QAction::triggered, this, &MainWindow::OpenWindow);

    m_pPostponeAction = new QAction(tr("&Add 5 mins"), this);
    m_pPostponeAction->setCheckable(true);
    connect(m_pPostponeAction, &QAction::triggered, this, &MainWindow::PostponeTheBreak);

    m_pAboutAction = new QAction(tr("A&bout..."), this);
    connect(m_pAboutAction, &QAction::triggered, qApp, &QApplication::aboutQt); // NOTE - change to about App

    m_pQuitAction = new QAction(tr("Really &quit"), this);
    connect(m_pQuitAction, &QAction::triggered, qApp, &QCoreApplication::quit);

    m_pOnTopAction = new QAction(tr("Always on &top"), this);
    m_pOnTopAction->setCheckable(true);
    connect(m_pOnTopAction, &QAction::triggered, [&](bool bOnTop) {
        m_pAppSettings->setValue("always_on_top", bOnTop);
        SetOnTop(bOnTop);
    });

    m_pOnStartUpAction = new QAction(tr("Run on &startup"), this);
    m_pOnStartUpAction->setCheckable(true);
    connect(m_pOnStartUpAction, &QAction::triggered, [&](bool bRunOnStartUp) {
        m_pAppSettings->setValue("run_on_startup", bRunOnStartUp);
        SetOnStartUp(bRunOnStartUp);
    });
}

void MainWindow::CreateMenu()
{
    m_pAppMenu = menuBar()->addMenu(tr("&App"));
    m_pAppMenu->addAction(m_pPostponeAction);
    m_pAppMenu->addSeparator();
    m_pAppMenu->addAction(m_pAboutAction);
    m_pAppMenu->addSeparator();
    m_pAppMenu->addAction(m_pQuitAction);

    m_pOptionsMenu = menuBar()->addMenu(tr("&Options"));
    m_pOptionsMenu->addAction(m_pOnTopAction);
    m_pOptionsMenu->addAction(m_pOnStartUpAction);
}

void MainWindow::OpenWindow()
{
    this->setWindowState(this->windowState() & ~Qt::WindowMinimized);
    this->show();
    this->activateWindow();
}

void MainWindow::PostponeTheBreak()
{
    m_pPostponeAction->setEnabled(false);
    m_nExtraWorkTime_ms = UserTimeSettings::ExtraWorkTime_s() * 1000;
}

void MainWindow::SetOnTop(bool bOnTop)
{
    if(bOnTop)
    {
        this->setWindowFlags(Qt::WindowStaysOnTopHint);
    }
    else
    {
        this->setWindowFlags(this->windowFlags() & (~Qt::WindowStaysOnTopHint));
    }
    this->show();
    this->activateWindow();
}

void MainWindow::SetOnStartUp(bool bRunOnStartUp)
{
    QSettings oSettings("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run", QSettings::NativeFormat);
    if (bRunOnStartUp)
    {
        const QString strNativeBinPath = QDir::toNativeSeparators(qApp->applicationFilePath());
        oSettings.setValue(QCoreApplication::applicationName(), strNativeBinPath);
    }
    else
    {
        oSettings.remove(QCoreApplication::applicationName());
    }
}

void MainWindow::SetIconByTime()
{
    int nWorkTime_ms = UserTimeSettings::WorkTime_s() * 1000 + m_nExtraWorkTime_ms;
    if(m_pLastUserInput->UserActiveTime_ms() > nWorkTime_ms)
    {
        SetTrayIcon(":/stop_icon.png");
    }
    else if(m_pLastUserInput->UserActiveTime_ms() < nWorkTime_ms &&  m_pLastUserInput->UserActiveTime_ms() > (nWorkTime_ms - UserTimeSettings::WarningTime_s()) * 1000)
    {
        SetTrayIcon(":/ready_icon.png");
    }
    else if(m_pLastUserInput->UserIdleTime_ms() > UserTimeSettings::RestTime_s())
    {
        SetTrayIcon(":/go_icon.png");
    }
}

MainWindow::MainWindow(QMainWindow *parent) : QMainWindow(parent)
{
    m_pLastUserInput = new UserInputWatcher(new SystemInput());

    m_pTrayIcon = new QSystemTrayIcon(this);

    CreateActions();
    CreateTrayIcon();
    SetTrayIcon(":/go_icon.png");

    CreateLayout();
    CreateMenu();
    LoadSettings();

    if(QSystemTrayIcon::isSystemTrayAvailable())
    {
        qDebug() << "tray is avaible";
    }

    connect(m_pTrayIcon, &QSystemTrayIcon::activated, [&](QSystemTrayIcon::ActivationReason eReason) {
        qDebug() << eReason;
        switch (eReason) {
        case QSystemTrayIcon::DoubleClick:
        case QSystemTrayIcon::Trigger:
            OpenWindow();
            break;
        default:
            break;
        }
    });

    connect(&m_oBeepTimer, &QTimer::timeout, [&]() {
        int nWorkTime_ms = UserTimeSettings::WorkTime_s() * 1000 + m_nExtraWorkTime_ms;
        if(m_pLastUserInput->UserActiveTime_ms() > nWorkTime_ms && m_pLastUserInput->PassedTolerance_ms() > 0)
        {
            QApplication::beep();
        }
    });

    connect(&m_oTimer, &QTimer::timeout, [&]() {

        SetIconByTime();
        m_pLastUserInput->UpdateLastUserInput();

        m_pPassedToleranceBar->setValue(m_pLastUserInput->PassedTolerance_ms() > m_pPassedToleranceBar->maximum() ? m_pPassedToleranceBar->maximum() : m_pLastUserInput->PassedTolerance_ms());

        m_pLabel->setText(QString("User idle time\t\t%1\nUser active time\t\t%2")
                          .arg(TimeFormat::GetMinsAndSeconds(m_pLastUserInput->UserIdleTime_ms()))
                          .arg(TimeFormat::GetMinsAndSeconds(m_pLastUserInput->UserActiveTime_ms())));

        m_pTrayIcon->setToolTip(QString(tr("Work time is %1 mins")).arg(TimeFormat::GetMins(m_pLastUserInput->UserActiveTime_ms())));

    });

    connect(m_pLastUserInput, &UserInputWatcher::NewWorkPeriod, [&]() {
        m_pPostponeAction->setEnabled(true);
        m_nExtraWorkTime_ms = 0;
    });

    m_oTimer.start(100);
    m_oBeepTimer.start(1100);
}

void MainWindow::closeEvent(QCloseEvent *event)
{
    if(m_pTrayIcon->isVisible())
    {
        hide();
        event->ignore();
    }
}
<commit_msg>fix in values loading<commit_after>#include "widget.h"

void MainWindow::CreateTrayIcon()
{
    QMenu* pTrayIconMenu = new QMenu(this);
    pTrayIconMenu->addAction(m_pOpenAction);
    pTrayIconMenu->addSeparator();
    pTrayIconMenu->addAction(m_pPostponeAction);
    pTrayIconMenu->addSeparator();
    pTrayIconMenu->addAction(m_pQuitAction);

    if(m_pTrayIcon)
    {
        m_pTrayIcon->setContextMenu(pTrayIconMenu);
    }
}

void MainWindow::SetTrayIcon(QString strIcon)
{
    if(strIcon != m_strSetTrayIcon && m_pTrayIcon)
    {
        QIcon icon(strIcon);
        m_pTrayIcon->setIcon(icon);
        m_pTrayIcon->setVisible(true);

        m_strSetTrayIcon = strIcon;
    }
}

void MainWindow::LoadSettings()
{
    m_pAppSettings = new QSettings(QCoreApplication::organizationName(), QCoreApplication::applicationName(), this);
    qDebug() << QCoreApplication::organizationName() << QCoreApplication::applicationName();

    UserTimeSettings::SetWorkTime_s(m_pAppSettings->value("work_time", UserTimeSettings::WorkTime_s()).toInt());
    UserTimeSettings::SetRestTime_s(m_pAppSettings->value("rest_time", UserTimeSettings::RestTime_s()).toInt());
    UserTimeSettings::SetToleranceTime_s(m_pAppSettings->value("tolerance_time", UserTimeSettings::ToleranceTime_s()).toInt());

    m_pOnTopAction->setChecked(m_pAppSettings->value("always_on_top", false).toBool());
    SetOnTop(m_pOnTopAction->isChecked());

    m_pOnStartUpAction->setChecked(m_pAppSettings->value("run_on_startup", false).toBool());
}

void MainWindow::CreateLayout()
{
    QVBoxLayout* pTimeLayout = new QVBoxLayout;

    // work spin box
    QHBoxLayout* pWorkLayout = new QHBoxLayout;
    QLabel* pWorkLabel = new QLabel(tr("Work time [mins]"));
    QSpinBox* pSpinWorkTime_s = new QSpinBox(this); // TODO - má tu být this? Nemá tu být některý child?
    pSpinWorkTime_s->setValue(UserTimeSettings::WorkTime_s() / 60);
    pSpinWorkTime_s->setMaximum(999);
    connect(pSpinWorkTime_s, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), [&](const int &nNewValue) {
        UserTimeSettings::SetWorkTime_s(nNewValue * 60);
        m_pAppSettings->setValue("work_time", UserTimeSettings::WorkTime_s());
    });
    pWorkLayout->addWidget(pWorkLabel);
    pWorkLayout->addWidget(pSpinWorkTime_s);

    // rest spin box
    QHBoxLayout* pRestLayout = new QHBoxLayout;
    QLabel* pRestLabel = new QLabel(tr("Rest time [mins]"));
    QSpinBox* pSpinRestTime_s = new QSpinBox(this);
    pSpinRestTime_s->setValue(UserTimeSettings::RestTime_s() / 60);
    pSpinRestTime_s->setMaximum(999);
    connect(pSpinRestTime_s, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), [&](const int &nNewValue) {
       UserTimeSettings::SetRestTime_s(nNewValue * 60);
       m_pAppSettings->setValue("rest_time", UserTimeSettings::RestTime_s());
    });
    pRestLayout->addWidget(pRestLabel);
    pRestLayout->addWidget(pSpinRestTime_s);

    // tolerance spin box
    QHBoxLayout* pToleranceLayout = new QHBoxLayout;
    QLabel* pToleranceLabel = new QLabel(tr("Tolerance time [s]"));
    QSpinBox* pSpinToleranceTime_s = new QSpinBox(this);
    pSpinToleranceTime_s->setValue(UserTimeSettings::ToleranceTime_s());
    pSpinToleranceTime_s->setMaximum(999);
    connect(pSpinToleranceTime_s, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), [&](const int &nNewValue) {
       UserTimeSettings::SetToleranceTime_s(nNewValue);
       m_pAppSettings->setValue("tolerance_time", UserTimeSettings::ToleranceTime_s());

    });
    pToleranceLayout->addWidget(pToleranceLabel);
    pToleranceLayout->addWidget(pSpinToleranceTime_s);

    // add all to vertical layout
    pTimeLayout->addLayout(pWorkLayout);
    pTimeLayout->addLayout(pRestLayout);
    pTimeLayout->addLayout(pToleranceLayout);

    // add label with info
    m_pLabel = new QLabel;

    QVBoxLayout* pMainLayout = new QVBoxLayout;
    pMainLayout->addLayout(pTimeLayout);

    m_pPassedToleranceBar = new QProgressBar(this);
    m_pPassedToleranceBar->setMaximum(0);
    m_pPassedToleranceBar->setMaximum(UserTimeSettings::ToleranceTime_s() * 1000);
    m_pPassedToleranceBar->setTextVisible(false);

    pMainLayout->addWidget(m_pPassedToleranceBar);
    pMainLayout->addWidget(m_pLabel);

    QWidget* pWidget = new QWidget(this);
    pWidget->setLayout(pMainLayout);
    this->setCentralWidget(pWidget);
}

void MainWindow::CreateActions()
{
    m_pOpenAction = new QAction(tr("&Open"), this);
    connect(m_pOpenAction, &QAction::triggered, this, &MainWindow::OpenWindow);

    m_pPostponeAction = new QAction(tr("&Add 5 mins"), this);
    m_pPostponeAction->setCheckable(true);
    connect(m_pPostponeAction, &QAction::triggered, this, &MainWindow::PostponeTheBreak);

    m_pAboutAction = new QAction(tr("A&bout..."), this);
    connect(m_pAboutAction, &QAction::triggered, qApp, &QApplication::aboutQt); // NOTE - change to about App

    m_pQuitAction = new QAction(tr("Really &quit"), this);
    connect(m_pQuitAction, &QAction::triggered, qApp, &QCoreApplication::quit);

    m_pOnTopAction = new QAction(tr("Always on &top"), this);
    m_pOnTopAction->setCheckable(true);
    connect(m_pOnTopAction, &QAction::triggered, [&](bool bOnTop) {
        m_pAppSettings->setValue("always_on_top", bOnTop);
        SetOnTop(bOnTop);
    });

    m_pOnStartUpAction = new QAction(tr("Run on &startup"), this);
    m_pOnStartUpAction->setCheckable(true);
    connect(m_pOnStartUpAction, &QAction::triggered, [&](bool bRunOnStartUp) {
        m_pAppSettings->setValue("run_on_startup", bRunOnStartUp);
        SetOnStartUp(bRunOnStartUp);
    });
}

void MainWindow::CreateMenu()
{
    m_pAppMenu = menuBar()->addMenu(tr("&App"));
    m_pAppMenu->addAction(m_pPostponeAction);
    m_pAppMenu->addSeparator();
    m_pAppMenu->addAction(m_pAboutAction);
    m_pAppMenu->addSeparator();
    m_pAppMenu->addAction(m_pQuitAction);

    m_pOptionsMenu = menuBar()->addMenu(tr("&Options"));
    m_pOptionsMenu->addAction(m_pOnTopAction);
    m_pOptionsMenu->addAction(m_pOnStartUpAction);
}

void MainWindow::OpenWindow()
{
    this->setWindowState(this->windowState() & ~Qt::WindowMinimized);
    this->show();
    this->activateWindow();
}

void MainWindow::PostponeTheBreak()
{
    m_pPostponeAction->setEnabled(false);
    m_nExtraWorkTime_ms = UserTimeSettings::ExtraWorkTime_s() * 1000;
}

void MainWindow::SetOnTop(bool bOnTop)
{
    if(bOnTop)
    {
        this->setWindowFlags(Qt::WindowStaysOnTopHint);
    }
    else
    {
        this->setWindowFlags(this->windowFlags() & (~Qt::WindowStaysOnTopHint));
    }
    this->show();
    this->activateWindow();
}

void MainWindow::SetOnStartUp(bool bRunOnStartUp)
{
    QSettings oSettings("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run", QSettings::NativeFormat);
    if (bRunOnStartUp)
    {
        const QString strNativeBinPath = QDir::toNativeSeparators(qApp->applicationFilePath());
        oSettings.setValue(QCoreApplication::applicationName(), strNativeBinPath);
    }
    else
    {
        oSettings.remove(QCoreApplication::applicationName());
    }
}

void MainWindow::SetIconByTime()
{
    int nWorkTime_ms = UserTimeSettings::WorkTime_s() * 1000 + m_nExtraWorkTime_ms;
    if(m_pLastUserInput->UserActiveTime_ms() > nWorkTime_ms)
    {
        SetTrayIcon(":/stop_icon.png");
    }
    else if(m_pLastUserInput->UserActiveTime_ms() < nWorkTime_ms &&  m_pLastUserInput->UserActiveTime_ms() > (nWorkTime_ms - UserTimeSettings::WarningTime_s()) * 1000)
    {
        SetTrayIcon(":/ready_icon.png");
    }
    else if(m_pLastUserInput->UserIdleTime_ms() > UserTimeSettings::RestTime_s())
    {
        SetTrayIcon(":/go_icon.png");
    }
}

MainWindow::MainWindow(QMainWindow *parent) : QMainWindow(parent)
{
    m_pLastUserInput = new UserInputWatcher(new SystemInput());

    m_pTrayIcon = new QSystemTrayIcon(this);

    CreateActions();
    CreateTrayIcon();
    SetTrayIcon(":/go_icon.png");

    LoadSettings();
    CreateLayout();
    CreateMenu();

    if(QSystemTrayIcon::isSystemTrayAvailable())
    {
        qDebug() << "tray is avaible";
    }

    connect(m_pTrayIcon, &QSystemTrayIcon::activated, [&](QSystemTrayIcon::ActivationReason eReason) {
        qDebug() << eReason;
        switch (eReason) {
        case QSystemTrayIcon::DoubleClick:
        case QSystemTrayIcon::Trigger:
            OpenWindow();
            break;
        default:
            break;
        }
    });

    connect(&m_oBeepTimer, &QTimer::timeout, [&]() {
        int nWorkTime_ms = UserTimeSettings::WorkTime_s() * 1000 + m_nExtraWorkTime_ms;
        if(m_pLastUserInput->UserActiveTime_ms() > nWorkTime_ms && m_pLastUserInput->PassedTolerance_ms() > 0)
        {
            QApplication::beep();
        }
    });

    connect(&m_oTimer, &QTimer::timeout, [&]() {

        SetIconByTime();
        m_pLastUserInput->UpdateLastUserInput();

        m_pPassedToleranceBar->setValue(m_pLastUserInput->PassedTolerance_ms() > m_pPassedToleranceBar->maximum() ? m_pPassedToleranceBar->maximum() : m_pLastUserInput->PassedTolerance_ms());

        m_pLabel->setText(QString("User idle time\t\t%1\nUser active time\t\t%2")
                          .arg(TimeFormat::GetMinsAndSeconds(m_pLastUserInput->UserIdleTime_ms()))
                          .arg(TimeFormat::GetMinsAndSeconds(m_pLastUserInput->UserActiveTime_ms())));

        m_pTrayIcon->setToolTip(QString(tr("Work time is %1 mins")).arg(TimeFormat::GetMins(m_pLastUserInput->UserActiveTime_ms())));

    });

    connect(m_pLastUserInput, &UserInputWatcher::NewWorkPeriod, [&]() {
        m_pPostponeAction->setEnabled(true);
        m_nExtraWorkTime_ms = 0;
    });

    m_oTimer.start(100);
    m_oBeepTimer.start(1100);
}

void MainWindow::closeEvent(QCloseEvent *event)
{
    if(m_pTrayIcon->isVisible())
    {
        hide();
        event->ignore();
    }
}
<|endoftext|>


<commit_before>/*!
 * \file
 * Implements asynchronous communication with a Riak server over objects.
 *
 * \author Andres Jaan Tack <ajtack@gmail.com>
 */
#include <boost/thread/mutex.hpp>
#include <riak/bucket.hxx>
#include <riak/message.hxx>
#include <riak/object.hxx>
#include <riak/riakclient.pb.h>
#include <riak/store.hxx>
#include <system_error>

//=============================================================================
namespace riak {
//=============================================================================

using std::placeholders::_1;
using std::placeholders::_2;
using std::placeholders::_3;

//=============================================================================
    namespace {
//=============================================================================

template <typename T>
void fulfill_promise (std::shared_ptr<boost::promise<T>> p, const T& v)
{
    p->set_value(v);
}

template <typename T>
void fail_promise (std::shared_ptr<boost::promise<T>> p, const std::exception& e)
{
    p->set_exception(boost::copy_exception(e));
}

//=============================================================================
    }   // namespace (anonymous)
//=============================================================================

boost::shared_future<void> object::put (const object::value& c)
        // const object_access_parameters& )
{
    std::shared_ptr<boost::promise<void>> promise(new boost::promise<void>());

    // Set up the appropriate callback.
    if (cache_is_hot_) {
        put_with_cached_vector_clock(promise, c);
    } else {
        using std::function;
        function<void()> on_successful_fetch =
                std::bind(&object::put_with_cached_vector_clock, shared_from_this(), promise, c);
        function<void(const std::exception&)> on_failed_fetch =
                std::bind(&fail_promise<void>, promise, _1);

        message::handler handle_fetch_response =
                std::bind(&object::on_fetch_response,
                        shared_from_this(),
                        on_successful_fetch,
                        on_failed_fetch,
                        _1, _2, _3);

        auto handle_buffered_fetch_response = message::make_buffering_handler(handle_whole_response);
        fetch_to (handle_buffered_fetch_response);
    }

    return promise->get_future();
}

boost::shared_future<boost::optional<object::siblings>> object::fetch () const
        // const object_access_parameters& p = store_.object_access_defaults() ) const
{
    typedef boost::optional<object::siblings> optval;
    std::shared_ptr<boost::promise<optval>> promise(new boost::promise<optval>());

    // Type inference should work here, but it doesn't derive correctly. Strange.
    using std::function;
    function<void()> on_successful_fetch = std::bind(&fulfill_promise<optval>, promise, std::ref(cached_siblings_));
    function<void(const std::exception&)> on_failed_fetch = std::bind(&fail_promise<optval>, promise, _1);
    message::handler handle_whole_response =
            std::bind(&object::on_fetch_response,
                    shared_from_this(),
                    on_successful_fetch,
                    on_failed_fetch,
                    _1, _2, _3);

    auto handle_buffered_response = message::make_buffering_handler(handle_whole_response);
    fetch_to (handle_buffered_response);

    return promise->get_future();
}

//=============================================================================
    namespace {
//=============================================================================

void update_cache (
        const RpbGetResp& response,
        boost::optional<object::siblings>& cached_siblings,
        boost::optional<std::string>& cached_vector_clock,
        boost::mutex& mutex)
{
    boost::unique_lock<boost::mutex> protect(mutex);
    if (not (response.has_unchanged() and response.unchanged())) {
        if (response.has_vclock()) {
            cached_siblings = response.content();
            cached_vector_clock = response.vclock();
        }
    }
}

//=============================================================================
    }
//=============================================================================

void object::fetch_to (message::buffering_handler& response_handler) const
{
    RpbGetReq request;
    request.set_bucket(this->bucket_);
    request.set_key(this->key());
    auto& overridden = overridden_access_parameters_;
    if (overridden.r )            request.set_r           (*overridden_access_parameters_.r);
    if (overridden.pr)            request.set_pr          (*overridden_access_parameters_.pr);
    if (overridden.basic_quorum)  request.set_basic_quorum(*overridden_access_parameters_.basic_quorum);
    if (overridden.notfound_ok)   request.set_notfound_ok (*overridden_access_parameters_.notfound_ok);
    if (cached_vector_clock_) request.set_if_modified(*cached_vector_clock_);
    request.set_head(false);
    request.set_deletedvclock(true);
    auto query = message::encode(request);

    store_.transmit_request(
            query.to_string(), response_handler, default_request_failure_parameters_.response_timeout);
}

bool object::on_fetch_response (
        std::function<void()> proceed_with_next_step,
        std::function<void(const std::exception&)> fail,
        const std::error_code& error,
        std::size_t bytes_received,
        const std::string& request) const
{
    // Note: This method assumes that it has been fed whole response objects. Anything less than
    // five bytes long is going to fail here in strange and wonderful ways. Use
    // message::make_buffering_handler!

    if (not error) {
        assert (bytes_received != 0);
        assert(bytes_received == request.size());

        RpbGetResp response;
        if (message::retrieve(response, request.size(), request)) {
            update_cache(response, cached_siblings_, cached_vector_clock_, mutex_);
            cache_is_hot_ = true;
            proceed_with_next_step();
        } else {
            fail(std::invalid_argument("Riak server's response was nonsensical."));
        }
    } else {
        fail(std::system_error(error));
    }

    // Whether we received a successful response or solk, we're done.
    return true;
}

void object::put_with_cached_vector_clock (
        std::shared_ptr<boost::promise<void>>& promise,
        const object::value& c)
{
    assert(!! cache_is_hot_);

    RpbPutReq request;
    request.set_bucket(this->bucket_);
    request.set_key(this->key());
    if (cached_vector_clock_)
        request.set_vclock(*cached_vector_clock_);

    // TODO: Really?
    request.mutable_content()->CopyFrom(c);

    auto& overridden = overridden_access_parameters_;
    if (overridden.w )  request.set_w (*overridden.w );
    if (overridden.dw)  request.set_dw(*overridden.dw);
    if (overridden.pw)  request.set_pw(*overridden.pw);

    // TODO: How do we control these options without being corny?
    request.set_return_body(false);
    request.set_if_not_modified(false);
    request.set_if_none_match(false);
    request.set_return_head(false);

    auto query = message::encode(request);
    message::handler handle_whole_request =
            std::bind(&object::on_put_response, shared_from_this(), promise, _1, _2, _3);

    store_.transmit_request(
            query.to_string(),
            handle_whole_request,
            default_request_failure_parameters_.response_timeout);
}

bool object::on_put_response (
    std::shared_ptr<boost::promise<void>>& p,
    const std::error_code& error,
    std::size_t bytes_received,
    const std::string& input) const
{
    if (not error) {
        RpbPutResp response;
        if (message::retrieve(response, bytes_received, input)) {
            boost::unique_lock<boost::mutex> protect(mutex_);
            if (response.has_vclock()   )  cached_vector_clock_ = response.vclock();
            if (response.content_size() > 0)  cached_siblings_ = response.content();
            // TODO: We assume that key is NULL, because we had to have a key to get here.
            p->set_value();
        } else {
            p->set_exception(boost::copy_exception(
                    std::invalid_argument("Riak server's response was nonsensical.")));
        }
    } else {
        p->set_exception(boost::copy_exception(std::system_error(error)));
    }

    return true;
}

//=============================================================================
}   // namespace riak
//=============================================================================
<commit_msg>Fixed a last-minute-renaming error.<commit_after>/*!
 * \file
 * Implements asynchronous communication with a Riak server over objects.
 *
 * \author Andres Jaan Tack <ajtack@gmail.com>
 */
#include <boost/thread/mutex.hpp>
#include <riak/bucket.hxx>
#include <riak/message.hxx>
#include <riak/object.hxx>
#include <riak/riakclient.pb.h>
#include <riak/store.hxx>
#include <system_error>

//=============================================================================
namespace riak {
//=============================================================================

using std::placeholders::_1;
using std::placeholders::_2;
using std::placeholders::_3;

//=============================================================================
    namespace {
//=============================================================================

template <typename T>
void fulfill_promise (std::shared_ptr<boost::promise<T>> p, const T& v)
{
    p->set_value(v);
}

template <typename T>
void fail_promise (std::shared_ptr<boost::promise<T>> p, const std::exception& e)
{
    p->set_exception(boost::copy_exception(e));
}

//=============================================================================
    }   // namespace (anonymous)
//=============================================================================

boost::shared_future<void> object::put (const object::value& c)
        // const object_access_parameters& )
{
    std::shared_ptr<boost::promise<void>> promise(new boost::promise<void>());

    // Set up the appropriate callback.
    if (cache_is_hot_) {
        put_with_cached_vector_clock(promise, c);
    } else {
        using std::function;
        function<void()> on_successful_fetch =
                std::bind(&object::put_with_cached_vector_clock, shared_from_this(), promise, c);
        function<void(const std::exception&)> on_failed_fetch =
                std::bind(&fail_promise<void>, promise, _1);

        message::handler handle_fetch_response =
                std::bind(&object::on_fetch_response,
                        shared_from_this(),
                        on_successful_fetch,
                        on_failed_fetch,
                        _1, _2, _3);

        auto handle_buffered_fetch_response = message::make_buffering_handler(handle_fetch_response);
        fetch_to (handle_buffered_fetch_response);
    }

    return promise->get_future();
}

boost::shared_future<boost::optional<object::siblings>> object::fetch () const
        // const object_access_parameters& p = store_.object_access_defaults() ) const
{
    typedef boost::optional<object::siblings> optval;
    std::shared_ptr<boost::promise<optval>> promise(new boost::promise<optval>());

    // Type inference should work here, but it doesn't derive correctly. Strange.
    using std::function;
    function<void()> on_successful_fetch = std::bind(&fulfill_promise<optval>, promise, std::ref(cached_siblings_));
    function<void(const std::exception&)> on_failed_fetch = std::bind(&fail_promise<optval>, promise, _1);
    message::handler handle_whole_response =
            std::bind(&object::on_fetch_response,
                    shared_from_this(),
                    on_successful_fetch,
                    on_failed_fetch,
                    _1, _2, _3);

    auto handle_buffered_response = message::make_buffering_handler(handle_whole_response);
    fetch_to (handle_buffered_response);

    return promise->get_future();
}

//=============================================================================
    namespace {
//=============================================================================

void update_cache (
        const RpbGetResp& response,
        boost::optional<object::siblings>& cached_siblings,
        boost::optional<std::string>& cached_vector_clock,
        boost::mutex& mutex)
{
    boost::unique_lock<boost::mutex> protect(mutex);
    if (not (response.has_unchanged() and response.unchanged())) {
        if (response.has_vclock()) {
            cached_siblings = response.content();
            cached_vector_clock = response.vclock();
        }
    }
}

//=============================================================================
    }
//=============================================================================

void object::fetch_to (message::buffering_handler& response_handler) const
{
    RpbGetReq request;
    request.set_bucket(this->bucket_);
    request.set_key(this->key());
    auto& overridden = overridden_access_parameters_;
    if (overridden.r )            request.set_r           (*overridden_access_parameters_.r);
    if (overridden.pr)            request.set_pr          (*overridden_access_parameters_.pr);
    if (overridden.basic_quorum)  request.set_basic_quorum(*overridden_access_parameters_.basic_quorum);
    if (overridden.notfound_ok)   request.set_notfound_ok (*overridden_access_parameters_.notfound_ok);
    if (cached_vector_clock_) request.set_if_modified(*cached_vector_clock_);
    request.set_head(false);
    request.set_deletedvclock(true);
    auto query = message::encode(request);

    store_.transmit_request(
            query.to_string(), response_handler, default_request_failure_parameters_.response_timeout);
}

bool object::on_fetch_response (
        std::function<void()> proceed_with_next_step,
        std::function<void(const std::exception&)> fail,
        const std::error_code& error,
        std::size_t bytes_received,
        const std::string& request) const
{
    // Note: This method assumes that it has been fed whole response objects. Anything less than
    // five bytes long is going to fail here in strange and wonderful ways. Use
    // message::make_buffering_handler!

    if (not error) {
        assert (bytes_received != 0);
        assert(bytes_received == request.size());

        RpbGetResp response;
        if (message::retrieve(response, request.size(), request)) {
            update_cache(response, cached_siblings_, cached_vector_clock_, mutex_);
            cache_is_hot_ = true;
            proceed_with_next_step();
        } else {
            fail(std::invalid_argument("Riak server's response was nonsensical."));
        }
    } else {
        fail(std::system_error(error));
    }

    // Whether we received a successful response or solk, we're done.
    return true;
}

void object::put_with_cached_vector_clock (
        std::shared_ptr<boost::promise<void>>& promise,
        const object::value& c)
{
    assert(!! cache_is_hot_);

    RpbPutReq request;
    request.set_bucket(this->bucket_);
    request.set_key(this->key());
    if (cached_vector_clock_)
        request.set_vclock(*cached_vector_clock_);

    // TODO: Really?
    request.mutable_content()->CopyFrom(c);

    auto& overridden = overridden_access_parameters_;
    if (overridden.w )  request.set_w (*overridden.w );
    if (overridden.dw)  request.set_dw(*overridden.dw);
    if (overridden.pw)  request.set_pw(*overridden.pw);

    // TODO: How do we control these options without being corny?
    request.set_return_body(false);
    request.set_if_not_modified(false);
    request.set_if_none_match(false);
    request.set_return_head(false);

    auto query = message::encode(request);
    message::handler handle_whole_request =
            std::bind(&object::on_put_response, shared_from_this(), promise, _1, _2, _3);

    store_.transmit_request(
            query.to_string(),
            handle_whole_request,
            default_request_failure_parameters_.response_timeout);
}

bool object::on_put_response (
    std::shared_ptr<boost::promise<void>>& p,
    const std::error_code& error,
    std::size_t bytes_received,
    const std::string& input) const
{
    if (not error) {
        RpbPutResp response;
        if (message::retrieve(response, bytes_received, input)) {
            boost::unique_lock<boost::mutex> protect(mutex_);
            if (response.has_vclock()   )  cached_vector_clock_ = response.vclock();
            if (response.content_size() > 0)  cached_siblings_ = response.content();
            // TODO: We assume that key is NULL, because we had to have a key to get here.
            p->set_value();
        } else {
            p->set_exception(boost::copy_exception(
                    std::invalid_argument("Riak server's response was nonsensical.")));
        }
    } else {
        p->set_exception(boost::copy_exception(std::system_error(error)));
    }

    return true;
}

//=============================================================================
}   // namespace riak
//=============================================================================
<|endoftext|>


<commit_before>#pragma once

#include "virtual_terminal.hpp"

namespace rltk {

constexpr color_t BLACK{0,0,0};
constexpr color_t WHITE{255,255,255};
constexpr color_t YELLOW{255,255,0};
constexpr color_t BLUE{0,0,255};

}
<commit_msg>A few more named colors.<commit_after>#pragma once

#include "virtual_terminal.hpp"

namespace rltk {

constexpr color_t BLACK{0,0,0};
constexpr color_t WHITE{255,255,255};
constexpr color_t YELLOW{255,255,0};
constexpr color_t BLUE{0,0,255};
constexpr color_t RED{255,0,0};
constexpr color_t GREEN{0,255,0};

}
<|endoftext|>


<commit_before>#ifndef VIENNAGRID_ALGORITHM_INTERSECT_HPP
#define VIENNAGRID_ALGORITHM_INTERSECT_HPP

/* =======================================================================
   Copyright (c) 2011-2012, Institute for Microelectronics,
                            Institute for Analysis and Scientific Computing,
                            TU Wien.

                            -----------------
                     ViennaGrid - The Vienna Grid Library
                            -----------------

   Authors:      Karl Rupp                           rupp@iue.tuwien.ac.at
                 Josef Weinbub                    weinbub@iue.tuwien.ac.at

   (A list of additional contributors can be found in the PDF manual)

   License:      MIT (X11), see file LICENSE in the base directory
======================================================================= */

#include "viennagrid/forwards.hpp"
#include "viennagrid/algorithm/numeric.hpp"
#include "viennagrid/algorithm/inner_prod.hpp"
#include "viennagrid/algorithm/norm.hpp"

namespace viennagrid
{

    namespace geometry
    {

        namespace interval
        {

            struct open_tag {};
            struct closed_tag {};

            template<typename tag0, typename tag1>
            open_tag intersect_tag( tag0, tag1 )
            { return open_tag(); }

            closed_tag intersect_tag ( closed_tag, closed_tag )
            { return closed_tag(); }

            inline bool is_open(open_tag) { return true; }
            inline bool is_open(closed_tag) { return false; }

            inline bool is_closed(open_tag) { return false; }
            inline bool is_closed(closed_tag) { return true; }

            struct open_open_tag
            {
                typedef open_tag first_tag;
                typedef open_tag second_tag;
            };

            struct open_closed_tag
            {
                typedef open_tag first_tag;
                typedef closed_tag second_tag;
            };

            struct closed_open_tag
            {
                typedef closed_tag first_tag;
                typedef open_tag second_tag;
            };

            struct closed_closed_tag
            {
                typedef closed_tag first_tag;
                typedef closed_tag second_tag;
            };

            template<typename dual_tag>
            typename dual_tag::first_tag first_tag( dual_tag )
            { return typename dual_tag::first_tag(); }

            template<typename dual_tag>
            typename dual_tag::second_tag second_tag( dual_tag )
            { return typename dual_tag::second_tag(); }

            inline open_open_tag make_tag( open_tag, open_tag )
            { return open_open_tag(); }

            inline open_closed_tag make_tag( open_tag, closed_tag )
            { return open_closed_tag(); }

            inline closed_open_tag make_tag( closed_tag, open_tag )
            { return closed_open_tag(); }

            inline closed_closed_tag make_tag( closed_tag, closed_tag )
            { return closed_closed_tag(); }

            template<typename numeric_type>
            bool greater( numeric_type ref, numeric_type to_test, open_tag )
            { return ref < to_test; }

            template<typename numeric_type>
            bool greater( numeric_type ref, numeric_type to_test, closed_tag )
            { return ref <= to_test; }

            template<typename numeric_type>
            bool less( numeric_type ref, numeric_type to_test, open_tag )
            { return ref > to_test; }

            template<typename numeric_type>
            bool less( numeric_type ref, numeric_type to_test, closed_tag )
            { return ref >= to_test; }

            template<typename numeric_type, typename first_tag_type, typename second_tag_type>
            bool point_in_interval( numeric_type first, first_tag_type first_tag, numeric_type second, second_tag_type second_tag, numeric_type to_test )
            {
                return (first <= second) ?
                    (greater(first, to_test, first_tag) && less(second, to_test, second_tag)) :
                    (greater(second, to_test, second_tag) && less(first, to_test, first_tag));
            }

            template<typename numeric_type, typename dual_tag>
            bool point_in_interval( numeric_type first, numeric_type second, dual_tag tag, numeric_type to_test )
            {
                return point_in_interval(first, first_tag(tag), second, second_tag(tag), to_test);
            }

            template<typename numeric_type, typename interval_0_tag_type, typename interval_1_tag_type>
            bool interval_intersect(numeric_type first_0, numeric_type second_0, interval_0_tag_type interval_0_tag,
                                    numeric_type first_1, numeric_type second_1, interval_1_tag_type interval_1_tag )
            {
                return point_in_interval( first_0, intersect_tag(first_tag(interval_0_tag), first_tag(interval_1_tag)), second_0, intersect_tag(second_tag(interval_0_tag), first_tag(interval_1_tag)), first_1 ) ||
                    point_in_interval( first_0, intersect_tag(first_tag(interval_0_tag), second_tag(interval_1_tag)), second_0, intersect_tag(second_tag(interval_0_tag), second_tag(interval_1_tag)), second_1 ) ||
                    point_in_interval( first_1, intersect_tag(first_tag(interval_1_tag), first_tag(interval_0_tag)), second_1, intersect_tag(second_tag(interval_1_tag), first_tag(interval_0_tag)), first_0 ) ||
                    point_in_interval( first_1, intersect_tag(first_tag(interval_1_tag), second_tag(interval_0_tag)), second_1, intersect_tag(second_tag(interval_1_tag), second_tag(interval_0_tag)), second_0 ) ||
                    ( (first_0 == first_1) && (second_0 == second_1) && (std::abs(second_0 - first_0) > 0) ) ||
                    ( (first_0 == second_1) && (second_0 == first_1) && (std::abs(second_0 - first_0) > 0) );
            }

        }

        template<typename point_type, typename numeric_config, typename line_tag>
        bool point_line_intersect(point_type const & p,
                                  point_type const & q0, point_type const & q1, line_tag tag,
                                  numeric_config nc )
        {
            typedef typename viennagrid::result_of::coord_type< point_type >::type coord_type;
            typedef typename numeric::result_of::numeric_type<numeric_config, coord_type>::type inner_numeric_type;

            point_type dir = q1 - q0;
            point_type lhs = p - q0;

            inner_numeric_type relative_eps = numeric::relative_tolerance(nc, viennagrid::norm_1(dir) );

//             std::cout << "  " << dir[0] << " " << lhs [0] << std::endl;

            if ( norm_1(dir) < relative_eps )
                return false;

            if ( std::abs(dir[0] * lhs[1] - lhs[0] * dir[1]) < relative_eps )
            {
                return (std::abs(dir[0]) < relative_eps) ?
                    interval::point_in_interval(coord_type(0), dir[1], tag, lhs[1]) :
                    interval::point_in_interval(coord_type(0), dir[0], tag, lhs[0]);
            }

            return false;
        }

        template <typename point_type, typename numeric_config, typename line1_tag, typename line2_tag>
        bool line_line_intersect(point_type const & v0, point_type const & v1, line1_tag tag1, //endpoints of first line
                                 point_type const & w0, point_type const & w1, line2_tag tag2, //endpoints of second line
                                 numeric_config nc )
        {
            //typedef point_t<CoordType, CoordinateSystem>  PointType;
            typedef typename viennagrid::result_of::coord_type< point_type >::type coord_type;
            typedef typename numeric::result_of::numeric_type<numeric_config, coord_type>::type inner_numeric_type;

            // write V(s) = v0 + s * (v1 - v0), s \in [0,1]
            //       W(t) = w0 + t * (w1 - w0), t \in [0,1]

            // compute s and t assuming V(s) and W(t) to be infinite lines:
            // cf. http://www.softsurfer.com/Archive/algorithm_0106/algorithm_0106.htm
            point_type dir_v = v1 - v0;  //direction vector for line V(s)
            point_type dir_w = w1 - w0;  //direction vector for line W(t)

            coord_type v_in_v = viennagrid::inner_prod(dir_v, dir_v);
            coord_type v_in_w = viennagrid::inner_prod(dir_v, dir_w);
            coord_type w_in_w = viennagrid::inner_prod(dir_w, dir_w);

            coord_type denominator = v_in_v * w_in_w - v_in_w * v_in_w;
//             std::cout << "denominator: " << denominator << std::endl;

            if ( std::abs(denominator) < numeric::relative_tolerance(nc, v_in_v * w_in_w) ) //lines parallel (up to round-off)
            {
                point_type lhs_v = w0 - v0;
                inner_numeric_type relative_eps = numeric::relative_tolerance(nc, viennagrid::norm_1(dir_v) );

                if ( std::abs(dir_v[0] * lhs_v[1] - lhs_v[0] * dir_v[1]) < relative_eps ) // lines share a common ray
                {
                    std::size_t index = (std::abs(dir_v[0]) < relative_eps) ? 1 : 0;

                    coord_type w_first = lhs_v[index];
                    coord_type w_second = w1[index] - v0[index];

                    return interval::interval_intersect( coord_type(0), dir_v[index], tag1, w_first, w_second, tag2 );
                }
                else
                    return false;
            }

            //Lines are not parallel: Compute minimizers s, t:
            point_type dir_distance = v0 - w0;  //any vector connecting two points on V and W

            //if (inner_prod(dir_distance, dir_distance) / v_in_v < 1e-10)  //v0 and w0 are the same point
            //  return std::make_pair(v0, w0);

            coord_type v_in_dir_distance = viennagrid::inner_prod(dir_v, dir_distance);
            coord_type w_in_dir_distance = viennagrid::inner_prod(dir_w, dir_distance);

            coord_type s = (v_in_w * w_in_dir_distance - w_in_w * v_in_dir_distance);
            coord_type t = (v_in_v * w_in_dir_distance - v_in_w * v_in_dir_distance);

            return point_in_interval(coord_type(0), denominator, tag1, s) && point_in_interval(coord_type(0), denominator, tag2, t);
        }

        template<typename point_iterator_type, typename linestrip_tag_type, typename point_type, typename line_tag_type, typename numeric_config>
        bool line_linestrip_intersect(point_iterator_type it1, const point_iterator_type & it_end, linestrip_tag_type linestrip_tag,
                                      const point_type & p0, const point_type & p1, line_tag_type line_tag,
                                      numeric_config nc )
        {
            if (it1 == it_end) return false;
            point_iterator_type it2 = it1++;

            for (; it2 != it_end; ++it1, ++it2)
            {
                if (line_line_intersect( p0, p1, line_tag, *it1, *it2, linestrip_tag, nc ))
                    return true;
            }

            return false;
        }

        template<typename point_iterator_type, typename linestrip_tag_type, typename point_type, typename line_tag_type, typename numeric_config>
        bool line_polygon_intersect(point_iterator_type it1, point_iterator_type it_end, linestrip_tag_type linestrip_tag,
                                    const point_type & p0, const point_type & p1, line_tag_type line_tag,
                                    numeric_config nc )
        {
            if (line_linestrip_intersect(it1, it_end, linestrip_tag, p0, p1, line_tag, nc)) return true;
            else return line_line_intersect( p0, p1, line_tag, *(--it_end), *it1, linestrip_tag, nc );
        }

    }

}

#endif

<commit_msg>added inline to solve linking problems<commit_after>#ifndef VIENNAGRID_ALGORITHM_INTERSECT_HPP
#define VIENNAGRID_ALGORITHM_INTERSECT_HPP

/* =======================================================================
   Copyright (c) 2011-2012, Institute for Microelectronics,
                            Institute for Analysis and Scientific Computing,
                            TU Wien.

                            -----------------
                     ViennaGrid - The Vienna Grid Library
                            -----------------

   Authors:      Karl Rupp                           rupp@iue.tuwien.ac.at
                 Josef Weinbub                    weinbub@iue.tuwien.ac.at

   (A list of additional contributors can be found in the PDF manual)

   License:      MIT (X11), see file LICENSE in the base directory
======================================================================= */

#include "viennagrid/forwards.hpp"
#include "viennagrid/algorithm/numeric.hpp"
#include "viennagrid/algorithm/inner_prod.hpp"
#include "viennagrid/algorithm/norm.hpp"

namespace viennagrid
{

    namespace geometry
    {

        namespace interval
        {

            struct open_tag {};
            struct closed_tag {};

            template<typename tag0, typename tag1>
            open_tag intersect_tag( tag0, tag1 )
            { return open_tag(); }

            inline closed_tag intersect_tag ( closed_tag, closed_tag )
            { return closed_tag(); }

            inline bool is_open(open_tag) { return true; }
            inline bool is_open(closed_tag) { return false; }

            inline bool is_closed(open_tag) { return false; }
            inline bool is_closed(closed_tag) { return true; }

            struct open_open_tag
            {
                typedef open_tag first_tag;
                typedef open_tag second_tag;
            };

            struct open_closed_tag
            {
                typedef open_tag first_tag;
                typedef closed_tag second_tag;
            };

            struct closed_open_tag
            {
                typedef closed_tag first_tag;
                typedef open_tag second_tag;
            };

            struct closed_closed_tag
            {
                typedef closed_tag first_tag;
                typedef closed_tag second_tag;
            };

            template<typename dual_tag>
            typename dual_tag::first_tag first_tag( dual_tag )
            { return typename dual_tag::first_tag(); }

            template<typename dual_tag>
            typename dual_tag::second_tag second_tag( dual_tag )
            { return typename dual_tag::second_tag(); }

            inline open_open_tag make_tag( open_tag, open_tag )
            { return open_open_tag(); }

            inline open_closed_tag make_tag( open_tag, closed_tag )
            { return open_closed_tag(); }

            inline closed_open_tag make_tag( closed_tag, open_tag )
            { return closed_open_tag(); }

            inline closed_closed_tag make_tag( closed_tag, closed_tag )
            { return closed_closed_tag(); }

            template<typename numeric_type>
            bool greater( numeric_type ref, numeric_type to_test, open_tag )
            { return ref < to_test; }

            template<typename numeric_type>
            bool greater( numeric_type ref, numeric_type to_test, closed_tag )
            { return ref <= to_test; }

            template<typename numeric_type>
            bool less( numeric_type ref, numeric_type to_test, open_tag )
            { return ref > to_test; }

            template<typename numeric_type>
            bool less( numeric_type ref, numeric_type to_test, closed_tag )
            { return ref >= to_test; }

            template<typename numeric_type, typename first_tag_type, typename second_tag_type>
            bool point_in_interval( numeric_type first, first_tag_type first_tag, numeric_type second, second_tag_type second_tag, numeric_type to_test )
            {
                return (first <= second) ?
                    (greater(first, to_test, first_tag) && less(second, to_test, second_tag)) :
                    (greater(second, to_test, second_tag) && less(first, to_test, first_tag));
            }

            template<typename numeric_type, typename dual_tag>
            bool point_in_interval( numeric_type first, numeric_type second, dual_tag tag, numeric_type to_test )
            {
                return point_in_interval(first, first_tag(tag), second, second_tag(tag), to_test);
            }

            template<typename numeric_type, typename interval_0_tag_type, typename interval_1_tag_type>
            bool interval_intersect(numeric_type first_0, numeric_type second_0, interval_0_tag_type interval_0_tag,
                                    numeric_type first_1, numeric_type second_1, interval_1_tag_type interval_1_tag )
            {
                return point_in_interval( first_0, intersect_tag(first_tag(interval_0_tag), first_tag(interval_1_tag)), second_0, intersect_tag(second_tag(interval_0_tag), first_tag(interval_1_tag)), first_1 ) ||
                    point_in_interval( first_0, intersect_tag(first_tag(interval_0_tag), second_tag(interval_1_tag)), second_0, intersect_tag(second_tag(interval_0_tag), second_tag(interval_1_tag)), second_1 ) ||
                    point_in_interval( first_1, intersect_tag(first_tag(interval_1_tag), first_tag(interval_0_tag)), second_1, intersect_tag(second_tag(interval_1_tag), first_tag(interval_0_tag)), first_0 ) ||
                    point_in_interval( first_1, intersect_tag(first_tag(interval_1_tag), second_tag(interval_0_tag)), second_1, intersect_tag(second_tag(interval_1_tag), second_tag(interval_0_tag)), second_0 ) ||
                    ( (first_0 == first_1) && (second_0 == second_1) && (std::abs(second_0 - first_0) > 0) ) ||
                    ( (first_0 == second_1) && (second_0 == first_1) && (std::abs(second_0 - first_0) > 0) );
            }

        }

        template<typename point_type, typename numeric_config, typename line_tag>
        bool point_line_intersect(point_type const & p,
                                  point_type const & q0, point_type const & q1, line_tag tag,
                                  numeric_config nc )
        {
            typedef typename viennagrid::result_of::coord_type< point_type >::type coord_type;
            typedef typename numeric::result_of::numeric_type<numeric_config, coord_type>::type inner_numeric_type;

            point_type dir = q1 - q0;
            point_type lhs = p - q0;

            inner_numeric_type relative_eps = numeric::relative_tolerance(nc, viennagrid::norm_1(dir) );

//             std::cout << "  " << dir[0] << " " << lhs [0] << std::endl;

            if ( norm_1(dir) < relative_eps )
                return false;

            if ( std::abs(dir[0] * lhs[1] - lhs[0] * dir[1]) < relative_eps )
            {
                return (std::abs(dir[0]) < relative_eps) ?
                    interval::point_in_interval(coord_type(0), dir[1], tag, lhs[1]) :
                    interval::point_in_interval(coord_type(0), dir[0], tag, lhs[0]);
            }

            return false;
        }

        template <typename point_type, typename numeric_config, typename line1_tag, typename line2_tag>
        bool line_line_intersect(point_type const & v0, point_type const & v1, line1_tag tag1, //endpoints of first line
                                 point_type const & w0, point_type const & w1, line2_tag tag2, //endpoints of second line
                                 numeric_config nc )
        {
            //typedef point_t<CoordType, CoordinateSystem>  PointType;
            typedef typename viennagrid::result_of::coord_type< point_type >::type coord_type;
            typedef typename numeric::result_of::numeric_type<numeric_config, coord_type>::type inner_numeric_type;

            // write V(s) = v0 + s * (v1 - v0), s \in [0,1]
            //       W(t) = w0 + t * (w1 - w0), t \in [0,1]

            // compute s and t assuming V(s) and W(t) to be infinite lines:
            // cf. http://www.softsurfer.com/Archive/algorithm_0106/algorithm_0106.htm
            point_type dir_v = v1 - v0;  //direction vector for line V(s)
            point_type dir_w = w1 - w0;  //direction vector for line W(t)

            coord_type v_in_v = viennagrid::inner_prod(dir_v, dir_v);
            coord_type v_in_w = viennagrid::inner_prod(dir_v, dir_w);
            coord_type w_in_w = viennagrid::inner_prod(dir_w, dir_w);

            coord_type denominator = v_in_v * w_in_w - v_in_w * v_in_w;
//             std::cout << "denominator: " << denominator << std::endl;

            if ( std::abs(denominator) < numeric::relative_tolerance(nc, v_in_v * w_in_w) ) //lines parallel (up to round-off)
            {
                point_type lhs_v = w0 - v0;
                inner_numeric_type relative_eps = numeric::relative_tolerance(nc, viennagrid::norm_1(dir_v) );

                if ( std::abs(dir_v[0] * lhs_v[1] - lhs_v[0] * dir_v[1]) < relative_eps ) // lines share a common ray
                {
                    std::size_t index = (std::abs(dir_v[0]) < relative_eps) ? 1 : 0;

                    coord_type w_first = lhs_v[index];
                    coord_type w_second = w1[index] - v0[index];

                    return interval::interval_intersect( coord_type(0), dir_v[index], tag1, w_first, w_second, tag2 );
                }
                else
                    return false;
            }

            //Lines are not parallel: Compute minimizers s, t:
            point_type dir_distance = v0 - w0;  //any vector connecting two points on V and W

            //if (inner_prod(dir_distance, dir_distance) / v_in_v < 1e-10)  //v0 and w0 are the same point
            //  return std::make_pair(v0, w0);

            coord_type v_in_dir_distance = viennagrid::inner_prod(dir_v, dir_distance);
            coord_type w_in_dir_distance = viennagrid::inner_prod(dir_w, dir_distance);

            coord_type s = (v_in_w * w_in_dir_distance - w_in_w * v_in_dir_distance);
            coord_type t = (v_in_v * w_in_dir_distance - v_in_w * v_in_dir_distance);

            return point_in_interval(coord_type(0), denominator, tag1, s) && point_in_interval(coord_type(0), denominator, tag2, t);
        }

        template<typename point_iterator_type, typename linestrip_tag_type, typename point_type, typename line_tag_type, typename numeric_config>
        bool line_linestrip_intersect(point_iterator_type it1, const point_iterator_type & it_end, linestrip_tag_type linestrip_tag,
                                      const point_type & p0, const point_type & p1, line_tag_type line_tag,
                                      numeric_config nc )
        {
            if (it1 == it_end) return false;
            point_iterator_type it2 = it1++;

            for (; it2 != it_end; ++it1, ++it2)
            {
                if (line_line_intersect( p0, p1, line_tag, *it1, *it2, linestrip_tag, nc ))
                    return true;
            }

            return false;
        }

        template<typename point_iterator_type, typename linestrip_tag_type, typename point_type, typename line_tag_type, typename numeric_config>
        bool line_polygon_intersect(point_iterator_type it1, point_iterator_type it_end, linestrip_tag_type linestrip_tag,
                                    const point_type & p0, const point_type & p1, line_tag_type line_tag,
                                    numeric_config nc )
        {
            if (line_linestrip_intersect(it1, it_end, linestrip_tag, p0, p1, line_tag, nc)) return true;
            else return line_line_intersect( p0, p1, line_tag, *(--it_end), *it1, linestrip_tag, nc );
        }

    }

}

#endif

<|endoftext|>


<commit_before><commit_msg>Init allocated SkBitmap pixels<commit_after><|endoftext|>


<commit_before>#include <limits>
#include <vector>
#include "Engine.h"
#include "Sphere.h"

Engine::Engine()
{
	lastRow = nullptr;
}

Engine::~Engine()
{
	delete [] lastRow;
}

void Engine::setTarget(Pixel *dest, unsigned int width, unsigned int height)
{
	this->dest = dest;
	this->width = width;
	this->height = height;
}

const Scene &Engine::getScene(void) const
{
	return scene;
}

Primitive *Engine::raytrace(const Ray &ray, Color &acc, unsigned int depth, double rIndex, double &dist)
{
	if (depth > TRACEDEPTH) return nullptr;
	// trace primary ray
	dist = std::numeric_limits<double>::max();
	Vector3 pi;
	primitives &primitives = scene.getPrimitives();
	Primitive *prim = nullptr;

	hitStatus result;

	// find the nearest intersection
	for (primitives::iterator s = primitives.begin(); s != primitives.end(); s++)
	{
		hitStatus res;
		if ((res = (*s)->Intersect(ray, dist)) != MISS)
		{
			prim = s->get();
			result = res; // 0 = miss, 1 = hit, -1 = hit from inside primitive
		}
	}

	// no hit, terminate ray
	if (!prim) return nullptr;

	// handle intersection
	if (prim->isLight())
	{
		// we hit a light, stop tracing
		acc = Color(1.0, 1.0, 1.0);
	}
	else
	{
		// determine color at point of intersection
		pi = ray.getOrigin() + (ray.getDirection() * dist);

		// trace lights
		for (primitives::iterator l = primitives.begin(); l != primitives.end(); l++)
		{
			if ((*l)->isLight())
			{
				Primitive* light = l->get();

				// calculate diffuse shading
				Vector3 L = ((Sphere *)light)->getCenter() - pi;
				L.normalize();
				Vector3 N = prim->getNormal(pi);
				if (prim->getMaterial().getDiffuse() > 0)
				{
					double dot = N * L;
					if (dot > 0)
					{
						double diff = dot * prim->getMaterial().getDiffuse();
						// add diffuse component to ray color
						acc += diff * (prim->getMaterial().getColor() * light->getMaterial().getColor());
					}
				}
			}
		}
	}
	// return pointer to primitive hit by primary ray
	return prim;
}

void Engine::initRender(void)
{
	// set first line to draw to
	currLine = 20;
	// set pixel buffer address of first pixel
	ppos = 20 * width;
	// screen plane in world space coordinates
	WX1 = -4.0;
	WX2 = 4.0;
	WY1 = SY = 3.0;
	WY2 = -3.0;
	// calculate deltas for interpolation
	DX = (WX2 - WX1) / width;
	DY = (WY2 - WY1) / height;
	SY += 20 * DY;

	// allocate space to store pointers to primitives for previous line
	lastRow = new Primitive*[width];
	memset(lastRow, 0, width * sizeof(Primitive *));
}

bool Engine::render(void)
{
	// TODO
	return false;
}<commit_msg>WIP: Engine render code<commit_after>#include <limits>
#include <vector>
#include "Engine.h"
#include "Sphere.h"

Engine::Engine()
{
	lastRow = nullptr;
}

Engine::~Engine()
{
	delete [] lastRow;
}

void Engine::setTarget(Pixel *dest, unsigned int width, unsigned int height)
{
	this->dest = dest;
	this->width = width;
	this->height = height;
}

const Scene &Engine::getScene(void) const
{
	return scene;
}

Primitive *Engine::raytrace(const Ray &ray, Color &acc, unsigned int depth, double rIndex, double &dist)
{
	if (depth > TRACEDEPTH) return nullptr;
	// trace primary ray
	dist = std::numeric_limits<double>::max();
	Vector3 pi;
	primitives &primitives = scene.getPrimitives();
	Primitive *prim = nullptr;

	hitStatus result;

	// find the nearest intersection
	for (primitives::iterator s = primitives.begin(); s != primitives.end(); s++)
	{
		hitStatus res;
		if ((res = (*s)->Intersect(ray, dist)) != MISS)
		{
			prim = s->get();
			result = res; // 0 = miss, 1 = hit, -1 = hit from inside primitive
		}
	}

	// no hit, terminate ray
	if (!prim) return nullptr;

	// handle intersection
	if (prim->isLight())
	{
		// we hit a light, stop tracing
		acc = Color(1.0, 1.0, 1.0);
	}
	else
	{
		// determine color at point of intersection
		pi = ray.getOrigin() + (ray.getDirection() * dist);

		// trace lights
		for (primitives::iterator l = primitives.begin(); l != primitives.end(); l++)
		{
			if ((*l)->isLight())
			{
				Primitive* light = l->get();

				// calculate diffuse shading
				Vector3 L = ((Sphere *)light)->getCenter() - pi;
				L.normalize();
				Vector3 N = prim->getNormal(pi);
				if (prim->getMaterial().getDiffuse() > 0)
				{
					double dot = N * L;
					if (dot > 0)
					{
						double diff = dot * prim->getMaterial().getDiffuse();
						// add diffuse component to ray color
						acc += diff * (prim->getMaterial().getColor() * light->getMaterial().getColor());
					}
				}
			}
		}
	}
	// return pointer to primitive hit by primary ray
	return prim;
}

void Engine::initRender(void)
{
	// set first line to draw to
	currLine = 20;
	// set pixel buffer address of first pixel
	ppos = 20 * width;
	// screen plane in world space coordinates
	WX1 = -4.0;
	WX2 = 4.0;
	WY1 = SY = 3.0;
	WY2 = -3.0;
	// calculate deltas for interpolation
	DX = (WX2 - WX1) / width;
	DY = (WY2 - WY1) / height;
	SY += 20 * DY;

	// allocate space to store pointers to primitives for previous line
	lastRow = new Primitive*[width];
	memset(lastRow, 0, width * sizeof(Primitive *));
}

bool Engine::render(void)
{
	// render scene
	Vector3 o(0.0, 0.0, -5.0);

	// initialize timer
	// TODO portable way to get time or at least a define
	// int msecs = GetTickCount();

	// reset last found primitive pointer
	Primitive* lastprim = nullptr;

	// render remaining lines
	for (unsigned int y = currLine; y < (height - 20); y++)
	{
		SX = WX1;
		// render pixels for current line
		for (unsigned int x = 0; x < width; x++)
		{
			// fire primary ray
			Color acc(0.0, 0.0, 0.0);
			Vector3 dir = Vector3(SX, SY, 0) - o;
			dir.normalize();
			Ray r(o, dir);
			double dist;
			Primitive* prim = raytrace(r, acc, 1, 1.0f, dist);
			int red = (int)(acc.R() * 256);
			int green = (int)(acc.G() * 256);
			int blue = (int)(acc.B() * 256);
			if (red > 255) red = 255;
			if (green > 255) green = 255;
			if (blue > 255) blue = 255;
			dest[ppos++] = (red << 16) + (green << 8) + blue;
			SX += DX;
		}
		SY += DY;

		// see if we've been working to long already
		// TODO
		//if ((GetTickCount() - msecs) > 100)
		//{
		//	// return control to windows so the screen gets updated
		//	m_CurrLine = y + 1;
		//	return false;
		//}
	}
	// all done
	return true;
}<|endoftext|>


<commit_before>// Copyright (c) 2017 ARM Limited
// All rights reserved
//
// The license below extends only to copyright in the software and shall
// not be construed as granting a license to any other intellectual
// property including but not limited to intellectual property relating
// to a hardware implementation of the functionality of the software
// licensed hereunder.  You may use the software subject to the license
// terms below provided that you ensure that this notice is replicated
// unmodified and in its entirety in all distributions of the software,
// modified or unmodified, in source code or in binary form.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met: redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer;
// redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution;
// neither the name of the copyright holders nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifndef __ARCH_GENERIC_VEC_PRED_REG_HH__
#define __ARCH_GENERIC_VEC_PRED_REG_HH__

#include <array>
#include <cassert>
#include <vector>

#include "arch/generic/vec_reg.hh"
#include "base/cprintf.hh"
#include "sim/serialize_handlers.hh"

template <size_t NumBits, bool Packed>
class VecPredRegContainer;

/// Predicate register view.
///
/// This generic class implements the View in an MVC pattern, similarly to
/// @see VecRegT. Since predicates are mainly used in conjunction with vectors
/// to specify which lanes are active in a vector operation, the class is
/// templated on the vector element type to simplify ISA definitions.
/// @tparam VecElem Type of the vector elements.
/// @tparam NumElems Number of vector elements making up the view.
/// @tparam Packed True if the predicate register relies on a packed
/// representation, i.e. adjacent bits refer to different vector elements
/// irrespective of the vector element size (e.g. this is the case for
/// AVX-512). If false, the predicate register relies on an unpacked
/// representation, where each bit refers to the corresponding byte in a vector
/// register (e.g. this is the case for ARM SVE).
/// @tparam Const True if the underlying container can be modified through
/// the view.
template <typename VecElem, size_t NumElems, bool Packed, bool Const>
class VecPredRegT
{
  protected:
    /// Size of the register in bits.
    static constexpr size_t NUM_BITS = Packed ? NumElems :
                                                sizeof(VecElem) * NumElems;

  public:
    /// Container type alias.
    using Container = typename std::conditional_t<
        Const,
        const VecPredRegContainer<NUM_BITS, Packed>,
        VecPredRegContainer<NUM_BITS, Packed>>;

  protected:
    // Alias for this type
    using MyClass = VecPredRegT<VecElem, NumElems, Packed, Const>;
    /// Container corresponding to this view.
    Container& container;

  public:
    VecPredRegT(Container& c) : container(c) {}

    /// Reset the register to an all-false value.
    template<bool Condition = !Const>
    std::enable_if_t<Condition> reset() { container.reset(); }

    /// Reset the register to an all-true value.
    template<bool Condition = !Const>
    std::enable_if_t<Condition> set() { container.set(); }

    template<bool Condition = !Const>
    std::enable_if_t<Condition, MyClass&>
    operator=(const MyClass& that)
    {
        container = that.container;
        return *this;
    }

    const bool&
    operator[](size_t idx) const
    {
        return container[idx * (Packed ? 1 : sizeof(VecElem))];
    }

    template<bool Condition = !Const>
    std::enable_if_t<Condition, bool&>
    operator[](size_t idx)
    {
        return container[idx * (Packed ? 1 : sizeof(VecElem))];
    }

    /// Return an element of the predicate register as it appears
    /// in the raw (untyped) internal representation
    uint8_t
    getRaw(size_t idx) const
    {
        return container.getBits(idx * (Packed ? 1 : sizeof(VecElem)),
                (Packed ? 1 : sizeof(VecElem)));
    }

    /// Write a raw value in an element of the predicate register
    template<bool Condition = !Const>
    std::enable_if_t<Condition>
    setRaw(size_t idx, uint8_t val)
    {
        container.setBits(idx * (Packed ? 1 : sizeof(VecElem)),
                (Packed ? 1 : sizeof(VecElem)), val);
    }

    /// Equality operator, required to compare thread contexts.
    template<typename VE2, size_t NE2, bool P2, bool C2>
    bool
    operator==(const VecPredRegT<VE2, NE2, P2, C2>& that) const
    {
        return container == that.container;
    }

    /// Inequality operator, required to compare thread contexts.
    template<typename VE2, size_t NE2, bool P2, bool C2>
    bool
    operator!=(const VecPredRegT<VE2, NE2, P2, C2>& that) const
    {
        return !operator==(that);
    }

    friend std::ostream&
    operator<<(std::ostream& os, const MyClass& p)
    {
        // Size must be greater than 0.
        for (int i = 0; i < NUM_BITS; i++)
            ccprintf(os, "%s%d", i ? " " : "[", (int)p.container[i]);
        ccprintf(os, "]");
        return os;
    }

    /// Returns true if the first active element of the register is true.
    /// @param mask Input mask used to filter the predicates to be tested.
    /// @param actual_num_elems Actual number of vector elements considered for
    /// the test (corresponding to the current vector length).
    template <bool MC>
    bool
    firstActive(const VecPredRegT<VecElem, NumElems, Packed, MC>& mask,
                size_t actual_num_elems) const
    {
        assert(actual_num_elems <= NumElems);
        for (int i = 0; i < actual_num_elems; ++i) {
            if (mask[i]) {
                return (*this)[i];
            }
        }
        return false;
    }

    /// Returns true if there are no active elements in the register.
    /// @param mask Input mask used to filter the predicates to be tested.
    /// @param actual_num_elems Actual number of vector elements considered for
    /// the test (corresponding to the current vector length).
    template <bool MC>
    bool
    noneActive(const VecPredRegT<VecElem, NumElems, Packed, MC>& mask,
               size_t actual_num_elems) const
    {
        assert(actual_num_elems <= NumElems);
        for (int i = 0; i < actual_num_elems; ++i) {
            if (mask[i] && operator[](i)) {
                return false;
            }
        }
        return true;
    }

    /// Returns true if the last active element of the register is true.
    /// @param mask Input mask used to filter the predicates to be tested.
    /// @param actual_num_elems Actual number of vector elements considered for
    /// the test (corresponding to the current vector length).
    template <bool MC>
    bool
    lastActive(const VecPredRegT<VecElem, NumElems, Packed, MC>& mask,
               size_t actual_num_elems) const
    {
        assert(actual_num_elems <= NumElems);
        for (int i = actual_num_elems - 1; i >= 0; --i) {
            if (mask[i]) {
                return operator[](i);
            }
        }
        return false;
    }
};

/// Generic predicate register container.
///
/// This generic class implements the Model in an MVC pattern, similarly to
/// @see VecRegContainer.
/// @tparam NumBits Size of the container in bits.
/// @tparam Packed See @VecRegT.
template <size_t NumBits, bool Packed>
class VecPredRegContainer
{
    static_assert(NumBits > 0,
                  "Size of a predicate register must be > 0");

  public:
    static constexpr size_t NUM_BITS = NumBits;
    using Container = std::array<bool, NumBits>;

  private:
    Container container;
    // Alias for this type
    using MyClass = VecPredRegContainer<NumBits, Packed>;

  public:
    VecPredRegContainer() {}
    VecPredRegContainer(const VecPredRegContainer &) = default;

    MyClass&
    operator=(const MyClass& that)
    {
        if (&that == this)
            return *this;
        container = that.container;
        return *this;
    }

    /// Required for de-serialization.
    MyClass&
    operator=(const std::vector<uint8_t>& that)
    {
        assert(that.size() == NUM_BITS);
        std::copy(that.begin(), that.end(), container.begin());
        return *this;
    }

    /// Resets the predicate register to an all-false register.
    void
    reset()
    {
        container.fill(false);
    }

    /// Sets the predicate register to an all-true value.
    void
    set()
    {
        container.fill(true);
    }

    /// Equality operator, required to compare thread contexts.
    template<size_t N2, bool P2>
    inline bool
    operator==(const VecPredRegContainer<N2, P2>& that) const
    {
        return NumBits == N2 && Packed == P2 && container == that.container;
    }

    /// Inequality operator, required to compare thread contexts.
    template<size_t N2, bool P2>
    bool
    operator!=(const VecPredRegContainer<N2, P2>& that) const
    {
        return !operator==(that);
    }

    /// Returns a reference to a specific element of the internal container.
    bool& operator[](size_t idx) { return container[idx]; }

    /// Returns a const reference to a specific element of the internal
    /// container.
    const bool& operator[](size_t idx) const { return container[idx]; }

    /// Returns a subset of bits starting from a specific element in the
    /// container.
    uint8_t
    getBits(size_t idx, uint8_t nbits) const
    {
        assert(nbits > 0 && nbits <= 8 && (idx + nbits - 1) < NumBits);
        uint8_t v = 0;
        idx = idx + nbits - 1;
        for (int i = 0; i < nbits; ++i, --idx) {
            v <<= 1;
            v |= container[idx];
        }
        return v;
    }

    /// Set a subset of bits starting from a specific element in the
    /// container.
    void
    setBits(size_t idx, uint8_t nbits, uint8_t bval)
    {
        assert(nbits > 0 && nbits <= 8 && (idx + nbits - 1) < NumBits);
        for (int i = 0; i < nbits; ++i, ++idx) {
            container[idx] = bval & 1;
            bval >>= 1;
        }
    }

    friend std::ostream&
    operator<<(std::ostream& os, const MyClass& p)
    {
        // Size must be greater than 0.
        for (int i = 0; i < NumBits; i++)
            ccprintf(os, "%s%d", i ? " " : "[", (int)p.container[i]);
        ccprintf(os, "]");
        return os;
    }

    friend ShowParam<VecPredRegContainer<NumBits, Packed>>;

    /// Create a view of this container.
    ///
    /// If NumElems is provided, the size of the container is bounds-checked,
    /// otherwise the size is inferred from the container size.
    /// @tparam VecElem Type of the vector elements.
    /// @tparam NumElems Number of vector elements making up the view.
    /// @{
    template <typename VecElem,
              size_t NumElems = (Packed ? NumBits : NumBits / sizeof(VecElem))>
    VecPredRegT<VecElem, NumElems, Packed, true> as() const
    {
        static_assert((Packed && NumElems <= NumBits) ||
                      (!Packed &&
                       NumBits % sizeof(VecElem) == 0 &&
                       sizeof(VecElem) * NumElems <= NumBits),
                      "Container size incompatible with view size");
        return VecPredRegT<VecElem, NumElems, Packed, true>(*this);
    }

    template <typename VecElem,
              size_t NumElems = (Packed ? NumBits : NumBits / sizeof(VecElem))>
    VecPredRegT<VecElem, NumElems, Packed, false> as()
    {
        static_assert((Packed && NumElems <= NumBits) ||
                      (!Packed &&
                       NumBits % sizeof(VecElem) == 0 &&
                       sizeof(VecElem) * NumElems <= NumBits),
                      "Container size incompatible with view size");
        return VecPredRegT<VecElem, NumElems, Packed, false>(*this);
    }
    /// @}
};

template <size_t NumBits, bool Packed>
struct ParseParam<VecPredRegContainer<NumBits, Packed>>
{
    static bool
    parse(const std::string &s, VecPredRegContainer<NumBits, Packed> &value)
    {
        int i = 0;
        for (const auto& c: s)
            value[i++] = (c == '1');
        return true;
    }
};

template <size_t NumBits, bool Packed>
struct ShowParam<VecPredRegContainer<NumBits, Packed>>
{
    static void
    show(std::ostream &os, const VecPredRegContainer<NumBits, Packed> &value)
    {
        for (auto b: value.container)
            ccprintf(os, "%d", b);
    }
};

/// Dummy type aliases and constants for architectures that do not implement
/// vector predicate registers.
/// @{
constexpr bool DummyVecPredRegHasPackedRepr = false;
using DummyVecPredReg = VecPredRegT<DummyVecElem, DummyNumVecElemPerVecReg,
                                    DummyVecPredRegHasPackedRepr, false>;
using DummyConstVecPredReg = VecPredRegT<DummyVecElem,
                                         DummyNumVecElemPerVecReg,
                                         DummyVecPredRegHasPackedRepr, true>;
using DummyVecPredRegContainer = DummyVecPredReg::Container;
constexpr size_t DummyVecPredRegSizeBits = 8;
/// @}

#endif  // __ARCH_GENERIC_VEC_PRED_REG_HH__
<commit_msg>arch: Collapse unused size parameter from "as" VecPredReg method.<commit_after>// Copyright (c) 2017 ARM Limited
// All rights reserved
//
// The license below extends only to copyright in the software and shall
// not be construed as granting a license to any other intellectual
// property including but not limited to intellectual property relating
// to a hardware implementation of the functionality of the software
// licensed hereunder.  You may use the software subject to the license
// terms below provided that you ensure that this notice is replicated
// unmodified and in its entirety in all distributions of the software,
// modified or unmodified, in source code or in binary form.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met: redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer;
// redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution;
// neither the name of the copyright holders nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifndef __ARCH_GENERIC_VEC_PRED_REG_HH__
#define __ARCH_GENERIC_VEC_PRED_REG_HH__

#include <array>
#include <cassert>
#include <vector>

#include "arch/generic/vec_reg.hh"
#include "base/cprintf.hh"
#include "sim/serialize_handlers.hh"

template <size_t NumBits, bool Packed>
class VecPredRegContainer;

/// Predicate register view.
///
/// This generic class implements the View in an MVC pattern, similarly to
/// @see VecRegT. Since predicates are mainly used in conjunction with vectors
/// to specify which lanes are active in a vector operation, the class is
/// templated on the vector element type to simplify ISA definitions.
/// @tparam VecElem Type of the vector elements.
/// @tparam NumElems Number of vector elements making up the view.
/// @tparam Packed True if the predicate register relies on a packed
/// representation, i.e. adjacent bits refer to different vector elements
/// irrespective of the vector element size (e.g. this is the case for
/// AVX-512). If false, the predicate register relies on an unpacked
/// representation, where each bit refers to the corresponding byte in a vector
/// register (e.g. this is the case for ARM SVE).
/// @tparam Const True if the underlying container can be modified through
/// the view.
template <typename VecElem, size_t NumElems, bool Packed, bool Const>
class VecPredRegT
{
  protected:
    /// Size of the register in bits.
    static constexpr size_t NUM_BITS = Packed ? NumElems :
                                                sizeof(VecElem) * NumElems;

  public:
    /// Container type alias.
    using Container = typename std::conditional_t<
        Const,
        const VecPredRegContainer<NUM_BITS, Packed>,
        VecPredRegContainer<NUM_BITS, Packed>>;

  protected:
    // Alias for this type
    using MyClass = VecPredRegT<VecElem, NumElems, Packed, Const>;
    /// Container corresponding to this view.
    Container& container;

  public:
    VecPredRegT(Container& c) : container(c) {}

    /// Reset the register to an all-false value.
    template<bool Condition = !Const>
    std::enable_if_t<Condition> reset() { container.reset(); }

    /// Reset the register to an all-true value.
    template<bool Condition = !Const>
    std::enable_if_t<Condition> set() { container.set(); }

    template<bool Condition = !Const>
    std::enable_if_t<Condition, MyClass&>
    operator=(const MyClass& that)
    {
        container = that.container;
        return *this;
    }

    const bool&
    operator[](size_t idx) const
    {
        return container[idx * (Packed ? 1 : sizeof(VecElem))];
    }

    template<bool Condition = !Const>
    std::enable_if_t<Condition, bool&>
    operator[](size_t idx)
    {
        return container[idx * (Packed ? 1 : sizeof(VecElem))];
    }

    /// Return an element of the predicate register as it appears
    /// in the raw (untyped) internal representation
    uint8_t
    getRaw(size_t idx) const
    {
        return container.getBits(idx * (Packed ? 1 : sizeof(VecElem)),
                (Packed ? 1 : sizeof(VecElem)));
    }

    /// Write a raw value in an element of the predicate register
    template<bool Condition = !Const>
    std::enable_if_t<Condition>
    setRaw(size_t idx, uint8_t val)
    {
        container.setBits(idx * (Packed ? 1 : sizeof(VecElem)),
                (Packed ? 1 : sizeof(VecElem)), val);
    }

    /// Equality operator, required to compare thread contexts.
    template<typename VE2, size_t NE2, bool P2, bool C2>
    bool
    operator==(const VecPredRegT<VE2, NE2, P2, C2>& that) const
    {
        return container == that.container;
    }

    /// Inequality operator, required to compare thread contexts.
    template<typename VE2, size_t NE2, bool P2, bool C2>
    bool
    operator!=(const VecPredRegT<VE2, NE2, P2, C2>& that) const
    {
        return !operator==(that);
    }

    friend std::ostream&
    operator<<(std::ostream& os, const MyClass& p)
    {
        // Size must be greater than 0.
        for (int i = 0; i < NUM_BITS; i++)
            ccprintf(os, "%s%d", i ? " " : "[", (int)p.container[i]);
        ccprintf(os, "]");
        return os;
    }

    /// Returns true if the first active element of the register is true.
    /// @param mask Input mask used to filter the predicates to be tested.
    /// @param actual_num_elems Actual number of vector elements considered for
    /// the test (corresponding to the current vector length).
    template <bool MC>
    bool
    firstActive(const VecPredRegT<VecElem, NumElems, Packed, MC>& mask,
                size_t actual_num_elems) const
    {
        assert(actual_num_elems <= NumElems);
        for (int i = 0; i < actual_num_elems; ++i) {
            if (mask[i]) {
                return (*this)[i];
            }
        }
        return false;
    }

    /// Returns true if there are no active elements in the register.
    /// @param mask Input mask used to filter the predicates to be tested.
    /// @param actual_num_elems Actual number of vector elements considered for
    /// the test (corresponding to the current vector length).
    template <bool MC>
    bool
    noneActive(const VecPredRegT<VecElem, NumElems, Packed, MC>& mask,
               size_t actual_num_elems) const
    {
        assert(actual_num_elems <= NumElems);
        for (int i = 0; i < actual_num_elems; ++i) {
            if (mask[i] && operator[](i)) {
                return false;
            }
        }
        return true;
    }

    /// Returns true if the last active element of the register is true.
    /// @param mask Input mask used to filter the predicates to be tested.
    /// @param actual_num_elems Actual number of vector elements considered for
    /// the test (corresponding to the current vector length).
    template <bool MC>
    bool
    lastActive(const VecPredRegT<VecElem, NumElems, Packed, MC>& mask,
               size_t actual_num_elems) const
    {
        assert(actual_num_elems <= NumElems);
        for (int i = actual_num_elems - 1; i >= 0; --i) {
            if (mask[i]) {
                return operator[](i);
            }
        }
        return false;
    }
};

/// Generic predicate register container.
///
/// This generic class implements the Model in an MVC pattern, similarly to
/// @see VecRegContainer.
/// @tparam NumBits Size of the container in bits.
/// @tparam Packed See @VecRegT.
template <size_t NumBits, bool Packed>
class VecPredRegContainer
{
    static_assert(NumBits > 0,
                  "Size of a predicate register must be > 0");

  public:
    static constexpr size_t NUM_BITS = NumBits;
    using Container = std::array<bool, NumBits>;

  private:
    Container container;
    // Alias for this type
    using MyClass = VecPredRegContainer<NumBits, Packed>;

  public:
    VecPredRegContainer() {}
    VecPredRegContainer(const VecPredRegContainer &) = default;

    MyClass&
    operator=(const MyClass& that)
    {
        if (&that == this)
            return *this;
        container = that.container;
        return *this;
    }

    /// Required for de-serialization.
    MyClass&
    operator=(const std::vector<uint8_t>& that)
    {
        assert(that.size() == NUM_BITS);
        std::copy(that.begin(), that.end(), container.begin());
        return *this;
    }

    /// Resets the predicate register to an all-false register.
    void
    reset()
    {
        container.fill(false);
    }

    /// Sets the predicate register to an all-true value.
    void
    set()
    {
        container.fill(true);
    }

    /// Equality operator, required to compare thread contexts.
    template<size_t N2, bool P2>
    inline bool
    operator==(const VecPredRegContainer<N2, P2>& that) const
    {
        return NumBits == N2 && Packed == P2 && container == that.container;
    }

    /// Inequality operator, required to compare thread contexts.
    template<size_t N2, bool P2>
    bool
    operator!=(const VecPredRegContainer<N2, P2>& that) const
    {
        return !operator==(that);
    }

    /// Returns a reference to a specific element of the internal container.
    bool& operator[](size_t idx) { return container[idx]; }

    /// Returns a const reference to a specific element of the internal
    /// container.
    const bool& operator[](size_t idx) const { return container[idx]; }

    /// Returns a subset of bits starting from a specific element in the
    /// container.
    uint8_t
    getBits(size_t idx, uint8_t nbits) const
    {
        assert(nbits > 0 && nbits <= 8 && (idx + nbits - 1) < NumBits);
        uint8_t v = 0;
        idx = idx + nbits - 1;
        for (int i = 0; i < nbits; ++i, --idx) {
            v <<= 1;
            v |= container[idx];
        }
        return v;
    }

    /// Set a subset of bits starting from a specific element in the
    /// container.
    void
    setBits(size_t idx, uint8_t nbits, uint8_t bval)
    {
        assert(nbits > 0 && nbits <= 8 && (idx + nbits - 1) < NumBits);
        for (int i = 0; i < nbits; ++i, ++idx) {
            container[idx] = bval & 1;
            bval >>= 1;
        }
    }

    friend std::ostream&
    operator<<(std::ostream& os, const MyClass& p)
    {
        // Size must be greater than 0.
        for (int i = 0; i < NumBits; i++)
            ccprintf(os, "%s%d", i ? " " : "[", (int)p.container[i]);
        ccprintf(os, "]");
        return os;
    }

    friend ShowParam<VecPredRegContainer<NumBits, Packed>>;

    /// Create a view of this container.
    ///
    /// @tparam VecElem Type of the vector elements.
    /// @{
    template <typename VecElem>
    VecPredRegT<VecElem, NumBits / sizeof(VecElem), Packed, true>
    as() const
    {
        static_assert(NumBits % sizeof(VecElem) == 0,
                "Container size incompatible with view size.");
        return VecPredRegT<VecElem, NumBits / sizeof(VecElem), Packed, true>(
                *this);
    }

    template <typename VecElem>
    VecPredRegT<VecElem, NumBits / sizeof(VecElem), Packed, false>
    as()
    {
        static_assert(NumBits % sizeof(VecElem) == 0,
                "Container size incompatible with view size.");
        return VecPredRegT<VecElem, NumBits / sizeof(VecElem), Packed, false>(
                *this);
    }
    /// @}
};

template <size_t NumBits, bool Packed>
struct ParseParam<VecPredRegContainer<NumBits, Packed>>
{
    static bool
    parse(const std::string &s, VecPredRegContainer<NumBits, Packed> &value)
    {
        int i = 0;
        for (const auto& c: s)
            value[i++] = (c == '1');
        return true;
    }
};

template <size_t NumBits, bool Packed>
struct ShowParam<VecPredRegContainer<NumBits, Packed>>
{
    static void
    show(std::ostream &os, const VecPredRegContainer<NumBits, Packed> &value)
    {
        for (auto b: value.container)
            ccprintf(os, "%d", b);
    }
};

/// Dummy type aliases and constants for architectures that do not implement
/// vector predicate registers.
/// @{
constexpr bool DummyVecPredRegHasPackedRepr = false;
using DummyVecPredReg = VecPredRegT<DummyVecElem, DummyNumVecElemPerVecReg,
                                    DummyVecPredRegHasPackedRepr, false>;
using DummyConstVecPredReg = VecPredRegT<DummyVecElem,
                                         DummyNumVecElemPerVecReg,
                                         DummyVecPredRegHasPackedRepr, true>;
using DummyVecPredRegContainer = DummyVecPredReg::Container;
constexpr size_t DummyVecPredRegSizeBits = 8;
/// @}

#endif  // __ARCH_GENERIC_VEC_PRED_REG_HH__
<|endoftext|>