<commit_before>#include "image.h"

#include <QDebug>
#include <QUndoStack>

Image::Image() :
    m_data()
{
}

Image::Image(const QSize &size, Image::Format format) :
    m_data(size, static_cast<QImage::Format>(format))
{
    undoStack = new QUndoStack(this);
}

Image::Image(const QString &fileName, const char *format) :
    m_data(fileName, format)
{
}

Image::Image(const QImage &image) :
    m_data(image)
{

}

Image::~Image()
{
    delete undoStack;
}

QImage &Image::data()
{
    return m_data;
}

Image::Format Image::format() const
{
    switch (m_data.format()) {
    case QImage::Format_Indexed8:
        return Indexed;
    case QImage::Format_ARGB32:
        return RGBA;
    default:
        return Invalid;
    }
}

void drawPixel(QImage &image, const QPoint &position, const uint index_or_rgb)
{
    if (image.rect().contains(position)) {
        image.setPixel(position, index_or_rgb);
    }
}

inline int sign(const int val)
{
    return (val > 0) ? 1 : ((val < 0) ? -1 : 0);
}

void doSpan(QImage &image, const QPoint &position, const uint x1, const uint index_or_rgb, void (*callback)(QImage &image, const QPoint &position, const uint index_or_rgb), const bool inclusive = true)
{
    const int end = x1 + (inclusive ? 1 : 0);
    for (int x = position.x(); x < end; x++) {
        callback(image, QPoint(x, position.y()), index_or_rgb);
    }
}

void drawSpan(QImage &image, const QPoint &position, const uint x1, const uint index_or_rgb, const bool inclusive = true)
{
    doSpan(image, position, x1, index_or_rgb, drawPixel, inclusive);
}

void doLine(QImage &image, const QPoint &a, const QPoint &b, const uint index_or_rgb, void (*callback)(QImage &image, const QPoint &position, const uint index_or_rgb), const bool inclusive = true)
{
    QPoint delta = b - a;
    const int stepX = sign(delta.x()), stepY = sign(delta.y());
    if (stepX == 0 && stepY == 0) {
        return;
    }
    const int sumStepX = abs(delta.y()), sumStepY = abs(delta.x());
//    if (!inclusive || sumStepX > 1 || sumStepY > 1) {
    if (sumStepX > 0 || sumStepY > 0) {
        const int limit = sumStepX * sumStepY;
        int sumX = sumStepX, sumY = sumStepY;
        int x = a.x(), y = a.y();
        qDebug() << sumStepX << "," << sumStepY << " | " << limit;
        do {
            qDebug() << sumX << "," << sumY;
            callback(image, QPoint(x, floor(y)), index_or_rgb);
            if (sumX >= sumY) {
                y += stepY;
                sumY += sumStepY;
            }
            if (sumX <= sumY) {
                x += stepX;
                sumX += sumStepX;
            }
        } while (sumX <= limit && sumY <= limit);
    }
//    if (inclusive) {
//        callback(image, QPoint(x, floor(y)), index_or_rgb);
//    }

}

void drawLine(QImage &image, const QPoint &a, const QPoint &b, const uint index_or_rgb)
{
    doLine(image, a, b, index_or_rgb, drawPixel);
}

void doRectangle(QImage &image, const QPoint &a, const QPoint &b, const uint index_or_rgb, void (*callback)(QImage &image, const QPoint &position, const uint index_or_rgb), const bool inclusive = true)
{
    int x0, x1;
    if (a.x() < b.x()) {
        x0 = a.x();
        x1 = b.x();
    }
    else {
        x0 = b.x();
        x1 = a.x();
    }
    int y0, y1;
    if (a.y() < b.y()) {
        y0 = a.y();
        y1 = b.y();
    }
    else {
        y0 = b.y();
        y1 = a.y();
    }
    if (!inclusive) {
        x1--;
        y1--;
    }
    int deltaX = x1 - x0;
    int deltaY = y1 - y0;
    doSpan(image, QPoint(x0, y0), x1, index_or_rgb, callback, true);
    if (deltaY > 0) {
        if (deltaY > 1) {
            for (int y = y0; y <= y1; y++) {
                callback(image, QPoint(x0, y), index_or_rgb);
                if (deltaX > 0) {
                    callback(image, QPoint(x1, y), index_or_rgb);
                }
            }
        }
        doSpan(image, QPoint(x0, y1), x1, index_or_rgb, callback, true);
    }
}

void drawRectangle(QImage &image, const QPoint &a, const QPoint &b, const uint index_or_rgb) {
    doRectangle(image, a, b, index_or_rgb, drawPixel);
}

void doRectangleFilled(QImage &image, const QPoint &a, const QPoint &b, const uint index_or_rgb, void (*callback)(QImage &image, const QPoint &position, const uint index_or_rgb), const bool inclusive = true)
{
    int x0, x1;
    if (a.x() < b.x()) {
        x0 = a.x();
        x1 = b.x();
    }
    else {
        x0 = b.x();
        x1 = a.x();
    }
    int y0, y1;
    if (a.y() < b.y()) {
        y0 = a.y();
        y1 = b.y();
    }
    else {
        y0 = b.y();
        y1 = a.y();
    }
    if (!inclusive) {
        x1--;
        y1--;
    }
    for (int y = y0; y <= y1; y++) {
        doSpan(image, QPoint(x0, y), x1, index_or_rgb, callback, true);
    }
}

void drawRectangleFilled(QImage &image, const QPoint &a, const QPoint &b, const uint index_or_rgb) {
    doRectangleFilled(image, a, b, index_or_rgb, drawPixel);
}

void drawEllipse(QImage &image, const QPoint &a, const QPoint &b, const uint index_or_rgb)
{
}

typedef void (*PointCallback)(QImage &image, const QPoint &position, const uint index_or_rgb);
typedef void (*SegmentCallback)(QImage &image, const QPoint &a, const QPoint &b, const uint index_or_rgb, void (*pointCallback)(QImage &image, const QPoint &position, const uint index_or_rgb), const bool inclusive);

void Image::stroke(const QPoint &a, const QPoint &b)
{
    PointCallback pointCallback = drawPixel;
    SegmentCallback segmentCallback = doRectangleFilled;
    uint colour;
    if (format() == Indexed) {
        colour = 1;
    }
    else if (format() == RGBA) {
        colour = qRgb(255, 0, 0);
    }
    segmentCallback(m_data, a, b, colour, pointCallback, false);
//    undoStack->push(new StrokeCommand(*m_image, a, b));
    emit changed();
}
<commit_msg>Fixed line function.<commit_after>#include "image.h"

#include <QDebug>
#include <QUndoStack>

Image::Image() :
    m_data()
{
}

Image::Image(const QSize &size, Image::Format format) :
    m_data(size, static_cast<QImage::Format>(format))
{
    undoStack = new QUndoStack(this);
}

Image::Image(const QString &fileName, const char *format) :
    m_data(fileName, format)
{
}

Image::Image(const QImage &image) :
    m_data(image)
{

}

Image::~Image()
{
    delete undoStack;
}

QImage &Image::data()
{
    return m_data;
}

Image::Format Image::format() const
{
    switch (m_data.format()) {
    case QImage::Format_Indexed8:
        return Indexed;
    case QImage::Format_ARGB32:
        return RGBA;
    default:
        return Invalid;
    }
}

void drawPixel(QImage &image, const QPoint &position, const uint index_or_rgb)
{
    if (image.rect().contains(position)) {
        image.setPixel(position, index_or_rgb);
    }
}

inline int sign(const int val)
{
    return (val > 0) ? 1 : ((val < 0) ? -1 : 0);
}

void doSpan(QImage &image, const QPoint &position, const uint x1, const uint index_or_rgb, void (*callback)(QImage &image, const QPoint &position, const uint index_or_rgb), const bool inclusive = true)
{
    const int end = x1 + (inclusive ? 1 : 0);
    for (int x = position.x(); x < end; x++) {
        callback(image, QPoint(x, position.y()), index_or_rgb);
    }
}

void drawSpan(QImage &image, const QPoint &position, const uint x1, const uint index_or_rgb, const bool inclusive = true)
{
    doSpan(image, position, x1, index_or_rgb, drawPixel, inclusive);
}

void doLine(QImage &image, const QPoint &a, const QPoint &b, const uint index_or_rgb, void (*callback)(QImage &image, const QPoint &position, const uint index_or_rgb), const bool inclusive = true)
{
    QPoint delta = b - a;
    const int stepX = sign(delta.x()), stepY = sign(delta.y());
    int sumStepX = abs(delta.y()), sumStepY = abs(delta.x());
    int x = a.x(), y = a.y();
    if (sumStepX > 0 || sumStepY > 0) {
        if (sumStepX == 0) {
            sumStepX = sumStepY;
        }
        if (sumStepY == 0) {
            sumStepY = sumStepX;
        }
        const int limit = sumStepX * sumStepY;
        int sumX = sumStepX, sumY = sumStepY;
//        qDebug() << sumStepX << "," << sumStepY << " | " << limit;
        do {
//            qDebug() << sumX << "," << sumY;
            callback(image, QPoint(x, y), index_or_rgb);
            if (sumX >= sumY) {
                y += stepY;
                sumY += sumStepY;
            }
            if (sumX <= sumY) {
                x += stepX;
                sumX += sumStepX;
            }
        } while (sumX <= limit && sumY <= limit);
    }
    if (inclusive) {
        callback(image, QPoint(x, y), index_or_rgb);
    }
}

void drawLine(QImage &image, const QPoint &a, const QPoint &b, const uint index_or_rgb)
{
    doLine(image, a, b, index_or_rgb, drawPixel);
}

void doRectangle(QImage &image, const QPoint &a, const QPoint &b, const uint index_or_rgb, void (*callback)(QImage &image, const QPoint &position, const uint index_or_rgb), const bool inclusive = true)
{
    int x0, x1;
    if (a.x() < b.x()) {
        x0 = a.x();
        x1 = b.x();
    }
    else {
        x0 = b.x();
        x1 = a.x();
    }
    int y0, y1;
    if (a.y() < b.y()) {
        y0 = a.y();
        y1 = b.y();
    }
    else {
        y0 = b.y();
        y1 = a.y();
    }
    if (!inclusive) {
        x1--;
        y1--;
    }
    int deltaX = x1 - x0;
    int deltaY = y1 - y0;
    doSpan(image, QPoint(x0, y0), x1, index_or_rgb, callback, true);
    if (deltaY > 0) {
        if (deltaY > 1) {
            for (int y = y0; y <= y1; y++) {
                callback(image, QPoint(x0, y), index_or_rgb);
                if (deltaX > 0) {
                    callback(image, QPoint(x1, y), index_or_rgb);
                }
            }
        }
        doSpan(image, QPoint(x0, y1), x1, index_or_rgb, callback, true);
    }
}

void drawRectangle(QImage &image, const QPoint &a, const QPoint &b, const uint index_or_rgb) {
    doRectangle(image, a, b, index_or_rgb, drawPixel);
}

void doRectangleFilled(QImage &image, const QPoint &a, const QPoint &b, const uint index_or_rgb, void (*callback)(QImage &image, const QPoint &position, const uint index_or_rgb), const bool inclusive = true)
{
    int x0, x1;
    if (a.x() < b.x()) {
        x0 = a.x();
        x1 = b.x();
    }
    else {
        x0 = b.x();
        x1 = a.x();
    }
    int y0, y1;
    if (a.y() < b.y()) {
        y0 = a.y();
        y1 = b.y();
    }
    else {
        y0 = b.y();
        y1 = a.y();
    }
    if (!inclusive) {
        x1--;
        y1--;
    }
    for (int y = y0; y <= y1; y++) {
        doSpan(image, QPoint(x0, y), x1, index_or_rgb, callback, true);
    }
}

void drawRectangleFilled(QImage &image, const QPoint &a, const QPoint &b, const uint index_or_rgb) {
    doRectangleFilled(image, a, b, index_or_rgb, drawPixel);
}

void drawEllipse(QImage &image, const QPoint &a, const QPoint &b, const uint index_or_rgb)
{
}

typedef void (*PointCallback)(QImage &image, const QPoint &position, const uint index_or_rgb);
typedef void (*SegmentCallback)(QImage &image, const QPoint &a, const QPoint &b, const uint index_or_rgb, void (*pointCallback)(QImage &image, const QPoint &position, const uint index_or_rgb), const bool inclusive);

void Image::stroke(const QPoint &a, const QPoint &b)
{
    PointCallback pointCallback = drawPixel;
    SegmentCallback segmentCallback = doLine;
    uint colour;
    if (format() == Indexed) {
        colour = 1;
    }
    else if (format() == RGBA) {
        colour = qRgb(255, 0, 0);
    }
    segmentCallback(m_data, a, b, colour, pointCallback, true);
//    undoStack->push(new StrokeCommand(*m_image, a, b));
    emit changed();
}
<|endoftext|>


<commit_before>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/test/chrome_process_util.h"

#include "chrome/test/ui/ui_test.h"

class ChromeProcessUtilTest : public UITest {
};

TEST_F(ChromeProcessUtilTest, SanityTest) {
  EXPECT_TRUE(IsBrowserRunning());
  ChromeProcessList processes = GetRunningChromeProcesses(browser_process_id());
  EXPECT_FALSE(processes.empty());
  QuitBrowser();
  EXPECT_FALSE(IsBrowserRunning());
  EXPECT_EQ(-1, browser_process_id());
  processes = GetRunningChromeProcesses(browser_process_id());
  EXPECT_TRUE(processes.empty());
}
<commit_msg>Mark ChromeProcessUtilTest.SanityTest as flaky.<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/test/chrome_process_util.h"

#include "chrome/test/ui/ui_test.h"

class ChromeProcessUtilTest : public UITest {
};

// Flaky on Mac only. See http://crbug.com/79175
TEST_F(ChromeProcessUtilTest, FLAKY_SanityTest) {
  EXPECT_TRUE(IsBrowserRunning());
  ChromeProcessList processes = GetRunningChromeProcesses(browser_process_id());
  EXPECT_FALSE(processes.empty());
  QuitBrowser();
  EXPECT_FALSE(IsBrowserRunning());
  EXPECT_EQ(-1, browser_process_id());
  processes = GetRunningChromeProcesses(browser_process_id());
  EXPECT_TRUE(processes.empty());
}
<|endoftext|>


<commit_before>#include "imageview.h"
#include "experimentcontext.h"
#include "resultspanel.h"
#include "../ori/OriWidgets.h"
#include "appconfig.h"

#include <QBoxLayout>
#include <QLabel>
#include <QVariant>
#include <QDebug>
#include <QDateTime>
#include <QPushButton>

#define WORST_PREDICTED_IMAGE_W 160
#define WORST_PREDICTED_IMAGE_H 120

ResultsPanel::ResultsPanel(ExperimentContext *context, QWidget *parent)
    : QFrame(parent), _updateIntervalMs(AppConfig::fpsUpdateIntervalMs())
{
    setObjectName("resultsPanel");

    _context = context;
    connect(_context, &ExperimentContext::experimentStarted, this, &ResultsPanel::experimentStarted);
    connect(_context, &ExperimentContext::newImageResult, this, &ResultsPanel::newImageResult);
    connect(_context, &ExperimentContext::currentResultChanged, this, &ResultsPanel::currentResultChanged);
    connect(_context, &ExperimentContext::modeChanged, this, &ResultsPanel::updateOnModeChanged);
    connect(_context, &ExperimentContext::zoomChanged, this, &ResultsPanel::updateOnEffectiveZoomChanged);
    connect(_context, &ExperimentContext::effectiveZoomChanged, this, &ResultsPanel::updateOnEffectiveZoomChanged);

    _infoImagesPerSec = makeInfoLabel();
    _infoPrecision = makeInfoLabel();
    _infoMetricTop1 = makeInfoLabel();
    _infoMetricTop5 = makeInfoLabel();

    _worstPredictedImage = new ImageView(WORST_PREDICTED_IMAGE_W, WORST_PREDICTED_IMAGE_H);

    auto panelCounters = makePanel({ Ori::Gui::makeTitle("IMAGES PER SECOND"), _infoImagesPerSec });
    _panelPrecision = makePanel({ Ori::Gui::makeTitle("AVERAGE PRECISION"), _infoPrecision });
    auto panelMetricTop1 = makePanel({ Ori::Gui::makeTitle("TOP-1"), _infoMetricTop1 });
    auto panelMetricTop5 = makePanel({ Ori::Gui::makeTitle("TOP-5"), _infoMetricTop5 });
    _panelMetrics = new QFrame;
    _panelMetrics->setLayout(Ori::Gui::layoutH(0, 0, { panelMetricTop1, panelMetricTop5 }));
    _panelWorstPrediction = makePanel({
        Ori::Gui::makeTitle("WORST PREDICTION"),
        Ori::Gui::layoutH(0, 0, { 0, _worstPredictedImage, 0}),
    });

    auto buttonZoomIn = new QPushButton;
    buttonZoomIn->setObjectName("buttonZoomIn");
    buttonZoomIn->setToolTip(tr("Zoom in"));
    buttonZoomIn->setIcon(QIcon(":/tools/zoom-in"));
    connect(buttonZoomIn, SIGNAL(clicked(bool)), _context, SLOT(zoomIn()));

    auto buttonZoomOut = new QPushButton;
    buttonZoomOut->setObjectName("buttonZoomOut");
    buttonZoomOut->setToolTip(tr("Zoom out"));
    buttonZoomOut->setIcon(QIcon(":/tools/zoom-out"));
    connect(buttonZoomOut, SIGNAL(clicked(bool)), _context, SLOT(zoomOut()));

    auto buttonZoomActual = new QPushButton;
    buttonZoomActual->setObjectName("buttonZoomActual");
    buttonZoomActual->setToolTip(tr("Actual size"));
    buttonZoomActual->setIcon(QIcon(":/tools/zoom-to-actual-size"));
    connect(buttonZoomActual, SIGNAL(clicked(bool)), _context, SLOT(zoomActual()));

    auto buttonZoomToFit = new QPushButton;
    buttonZoomToFit->setObjectName("buttonZoomToFit");
    buttonZoomToFit->setToolTip(tr("Zoom to fit"));
    buttonZoomToFit->setIcon(QIcon(":/tools/zoom-to-fit"));
    connect(buttonZoomToFit, SIGNAL(clicked(bool)), _context, SLOT(zoomToFit()));

    _infoZoom = new QLabel;
    _infoZoom->setAlignment(Qt::AlignTop | Qt::AlignRight);
    _infoZoom->setProperty("qss-role", "link");

    auto zoomLayout = Ori::Gui::layoutH({buttonZoomActual, 0, buttonZoomOut, 0, buttonZoomIn, 0, buttonZoomToFit});
    _panelZoom = makePanel({
        Ori::Gui::layoutH({ Ori::Gui::makeTitle("ZOOM"), 0, _infoZoom }),
        zoomLayout
    });

    auto buttonFirst = new QPushButton;
    buttonFirst->setObjectName("buttonFirst");
    buttonFirst->setToolTip(tr("First image"));
    buttonFirst->setIcon(QIcon(":/tools/first-img"));
    connect(buttonFirst, SIGNAL(clicked(bool)), _context, SLOT(gotoFirstResult()));

    auto buttonPrev = new QPushButton;
    buttonPrev->setObjectName("buttonPrev");
    buttonPrev->setToolTip(tr("Previous image"));
    buttonPrev->setIcon(QIcon(":/tools/prev-img"));
    connect(buttonPrev, SIGNAL(clicked(bool)), _context, SLOT(gotoPrevResult()));

    auto buttonNext = new QPushButton;
    buttonNext->setObjectName("buttonNext");
    buttonNext->setToolTip(tr("Next image"));
    buttonNext->setIcon(QIcon(":/tools/next-img"));
    connect(buttonNext, SIGNAL(clicked(bool)), _context, SLOT(gotoNextResult()));

    auto buttonLast = new QPushButton;
    buttonLast->setObjectName("buttonLast");
    buttonLast->setToolTip(tr("Last image"));
    buttonLast->setIcon(QIcon(":/tools/last-img"));
    connect(buttonLast, SIGNAL(clicked(bool)), _context, SLOT(gotoLastResult()));

    _infoNav = new QLabel;
    _infoNav->setAlignment(Qt::AlignTop | Qt::AlignRight);
    _infoNav->setProperty("qss-role", "link");

    auto navLayout = Ori::Gui::layoutH({buttonFirst, 0, buttonPrev, 0, buttonNext, 0, buttonLast});
    _panelNav = makePanel({
        Ori::Gui::layoutH({ Ori::Gui::makeTitle("NAVIGATION"), 0, _infoNav }),
        navLayout
    });

    setLayout(Ori::Gui::layoutV(0, 0,
        { panelCounters, _panelPrecision, _panelZoom, _panelNav, _panelMetrics, _panelWorstPrediction, 0 }));

    resetInfo();
    updateOnModeChanged(AppConfig::currentMode().value<Mode>());
    updateOnEffectiveZoomChanged(AppConfig::zoom());
}

QLabel* ResultsPanel::makeInfoLabel(const QString &role) {
    auto label = new QLabel;
    label->setProperty("qss-role", role.isEmpty() ? QString("info-label") : role);
    return label;
}

QFrame* ResultsPanel::makePanel(const std::initializer_list<QObject *> &items, const QString &objectName) {
    auto panel = new QFrame;
    panel->setProperty("qss-role", "results-panel");
    panel->setObjectName(objectName);
    panel->setLayout(Ori::Gui::layoutV(0, 0, items));
    return panel;
}

void ResultsPanel::experimentStarted(bool resume) {
    if (!resume) {
        resetInfo();
    }
}

void ResultsPanel::currentResultChanged(int currentResult, int resultCount) {
    _infoNav->setText(QString("%1 / %2").arg(currentResult + 1).arg(resultCount));
}

void ResultsPanel::newImageResult(ImageResult ir) {
    qint64 curTimeMs = QDateTime::currentMSecsSinceEpoch();
    if (curTimeMs - _lastUpdateMs > _updateIntervalMs) {
        _infoImagesPerSec->setText(QString(QStringLiteral("%1")).arg(ir.imagesPerSecond(), 0, 'f', 2));
        _infoPrecision->setText(QString(QStringLiteral("%1")).arg(_context->precision().avg, 0, 'f', 2));
        _infoMetricTop1->setText(QString::number(_context->top1().avg, 'f', 2));
        _infoMetricTop5->setText(QString::number(_context->top5().avg, 'f', 2));

        double accuracyDelta = ir.accuracyDelta();
        if (accuracyDelta > _worstAccuracyDelta) {
            _worstAccuracyDelta = accuracyDelta;
            _worstPredictedImage->loadImage(ir.imageFile);
            _worstPredictedImage->setToolTip(QString(QStringLiteral("%1\nTop1: %2\nCorrect: %3"))
                                             .arg(ir.imageFile)
                                             .arg(ir.predictions[0].str())
                                             .arg(ir.findCorrect()->str()));
        }
        _lastUpdateMs = curTimeMs;
    }
}

void ResultsPanel::resetInfo() {
    _infoImagesPerSec->setText("N/A");
    _infoPrecision->setText("N/A");
    _infoMetricTop1->setText("N/A");
    _infoMetricTop5->setText("N/A");
    _worstAccuracyDelta = 0;
    _worstPredictedImage->clearImage();
    _worstPredictedImage->setToolTip("");
    _lastUpdateMs = 0;
    _infoNav->setText("");
}

void ResultsPanel::updateOnModeChanged(Mode mode) {
    bool v = mode.type == Mode::Type::CLASSIFICATION;
    _panelMetrics->setVisible(v);
    _panelWorstPrediction->setVisible(v);
    _panelPrecision->setVisible(!v);
    _panelZoom->setVisible(!v);
    _panelNav->setVisible(!v);
}

void ResultsPanel::updateOnEffectiveZoomChanged(double z) {
    int p = z * 100;
    _infoZoom->setText(QString("%1%").arg(p));
}
<commit_msg>Stick zoom and navigation controls to the bottom<commit_after>#include "imageview.h"
#include "experimentcontext.h"
#include "resultspanel.h"
#include "../ori/OriWidgets.h"
#include "appconfig.h"

#include <QBoxLayout>
#include <QLabel>
#include <QVariant>
#include <QDebug>
#include <QDateTime>
#include <QPushButton>

#define WORST_PREDICTED_IMAGE_W 160
#define WORST_PREDICTED_IMAGE_H 120

ResultsPanel::ResultsPanel(ExperimentContext *context, QWidget *parent)
    : QFrame(parent), _updateIntervalMs(AppConfig::fpsUpdateIntervalMs())
{
    setObjectName("resultsPanel");

    _context = context;
    connect(_context, &ExperimentContext::experimentStarted, this, &ResultsPanel::experimentStarted);
    connect(_context, &ExperimentContext::newImageResult, this, &ResultsPanel::newImageResult);
    connect(_context, &ExperimentContext::currentResultChanged, this, &ResultsPanel::currentResultChanged);
    connect(_context, &ExperimentContext::modeChanged, this, &ResultsPanel::updateOnModeChanged);
    connect(_context, &ExperimentContext::zoomChanged, this, &ResultsPanel::updateOnEffectiveZoomChanged);
    connect(_context, &ExperimentContext::effectiveZoomChanged, this, &ResultsPanel::updateOnEffectiveZoomChanged);

    _infoImagesPerSec = makeInfoLabel();
    _infoPrecision = makeInfoLabel();
    _infoMetricTop1 = makeInfoLabel();
    _infoMetricTop5 = makeInfoLabel();

    _worstPredictedImage = new ImageView(WORST_PREDICTED_IMAGE_W, WORST_PREDICTED_IMAGE_H);

    auto panelCounters = makePanel({ Ori::Gui::makeTitle("IMAGES PER SECOND"), _infoImagesPerSec });
    _panelPrecision = makePanel({ Ori::Gui::makeTitle("AVERAGE PRECISION"), _infoPrecision });
    auto panelMetricTop1 = makePanel({ Ori::Gui::makeTitle("TOP-1"), _infoMetricTop1 });
    auto panelMetricTop5 = makePanel({ Ori::Gui::makeTitle("TOP-5"), _infoMetricTop5 });
    _panelMetrics = new QFrame;
    _panelMetrics->setLayout(Ori::Gui::layoutH(0, 0, { panelMetricTop1, panelMetricTop5 }));
    _panelWorstPrediction = makePanel({
        Ori::Gui::makeTitle("WORST PREDICTION"),
        Ori::Gui::layoutH(0, 0, { 0, _worstPredictedImage, 0}),
    });

    auto buttonZoomIn = new QPushButton;
    buttonZoomIn->setObjectName("buttonZoomIn");
    buttonZoomIn->setToolTip(tr("Zoom in"));
    buttonZoomIn->setIcon(QIcon(":/tools/zoom-in"));
    connect(buttonZoomIn, SIGNAL(clicked(bool)), _context, SLOT(zoomIn()));

    auto buttonZoomOut = new QPushButton;
    buttonZoomOut->setObjectName("buttonZoomOut");
    buttonZoomOut->setToolTip(tr("Zoom out"));
    buttonZoomOut->setIcon(QIcon(":/tools/zoom-out"));
    connect(buttonZoomOut, SIGNAL(clicked(bool)), _context, SLOT(zoomOut()));

    auto buttonZoomActual = new QPushButton;
    buttonZoomActual->setObjectName("buttonZoomActual");
    buttonZoomActual->setToolTip(tr("Actual size"));
    buttonZoomActual->setIcon(QIcon(":/tools/zoom-to-actual-size"));
    connect(buttonZoomActual, SIGNAL(clicked(bool)), _context, SLOT(zoomActual()));

    auto buttonZoomToFit = new QPushButton;
    buttonZoomToFit->setObjectName("buttonZoomToFit");
    buttonZoomToFit->setToolTip(tr("Zoom to fit"));
    buttonZoomToFit->setIcon(QIcon(":/tools/zoom-to-fit"));
    connect(buttonZoomToFit, SIGNAL(clicked(bool)), _context, SLOT(zoomToFit()));

    _infoZoom = new QLabel;
    _infoZoom->setAlignment(Qt::AlignTop | Qt::AlignRight);
    _infoZoom->setProperty("qss-role", "link");

    auto zoomLayout = Ori::Gui::layoutH({buttonZoomActual, 0, buttonZoomOut, 0, buttonZoomIn, 0, buttonZoomToFit});
    _panelZoom = makePanel({
        Ori::Gui::layoutH({ Ori::Gui::makeTitle("ZOOM"), 0, _infoZoom }),
        zoomLayout
    });

    auto buttonFirst = new QPushButton;
    buttonFirst->setObjectName("buttonFirst");
    buttonFirst->setToolTip(tr("First image"));
    buttonFirst->setIcon(QIcon(":/tools/first-img"));
    connect(buttonFirst, SIGNAL(clicked(bool)), _context, SLOT(gotoFirstResult()));

    auto buttonPrev = new QPushButton;
    buttonPrev->setObjectName("buttonPrev");
    buttonPrev->setToolTip(tr("Previous image"));
    buttonPrev->setIcon(QIcon(":/tools/prev-img"));
    connect(buttonPrev, SIGNAL(clicked(bool)), _context, SLOT(gotoPrevResult()));

    auto buttonNext = new QPushButton;
    buttonNext->setObjectName("buttonNext");
    buttonNext->setToolTip(tr("Next image"));
    buttonNext->setIcon(QIcon(":/tools/next-img"));
    connect(buttonNext, SIGNAL(clicked(bool)), _context, SLOT(gotoNextResult()));

    auto buttonLast = new QPushButton;
    buttonLast->setObjectName("buttonLast");
    buttonLast->setToolTip(tr("Last image"));
    buttonLast->setIcon(QIcon(":/tools/last-img"));
    connect(buttonLast, SIGNAL(clicked(bool)), _context, SLOT(gotoLastResult()));

    _infoNav = new QLabel;
    _infoNav->setAlignment(Qt::AlignTop | Qt::AlignRight);
    _infoNav->setProperty("qss-role", "link");

    auto navLayout = Ori::Gui::layoutH({buttonFirst, 0, buttonPrev, 0, buttonNext, 0, buttonLast});
    _panelNav = makePanel({
        Ori::Gui::layoutH({ Ori::Gui::makeTitle("NAVIGATION"), 0, _infoNav }),
        navLayout
    });

    setLayout(Ori::Gui::layoutV(0, 0,
        { panelCounters, _panelPrecision, _panelMetrics, _panelWorstPrediction, 0, _panelZoom, _panelNav }));

    resetInfo();
    updateOnModeChanged(AppConfig::currentMode().value<Mode>());
    updateOnEffectiveZoomChanged(AppConfig::zoom());
}

QLabel* ResultsPanel::makeInfoLabel(const QString &role) {
    auto label = new QLabel;
    label->setProperty("qss-role", role.isEmpty() ? QString("info-label") : role);
    return label;
}

QFrame* ResultsPanel::makePanel(const std::initializer_list<QObject *> &items, const QString &objectName) {
    auto panel = new QFrame;
    panel->setProperty("qss-role", "results-panel");
    panel->setObjectName(objectName);
    panel->setLayout(Ori::Gui::layoutV(0, 0, items));
    return panel;
}

void ResultsPanel::experimentStarted(bool resume) {
    if (!resume) {
        resetInfo();
    }
}

void ResultsPanel::currentResultChanged(int currentResult, int resultCount) {
    _infoNav->setText(QString("%1 / %2").arg(currentResult + 1).arg(resultCount));
}

void ResultsPanel::newImageResult(ImageResult ir) {
    qint64 curTimeMs = QDateTime::currentMSecsSinceEpoch();
    if (curTimeMs - _lastUpdateMs > _updateIntervalMs) {
        _infoImagesPerSec->setText(QString(QStringLiteral("%1")).arg(ir.imagesPerSecond(), 0, 'f', 2));
        _infoPrecision->setText(QString(QStringLiteral("%1")).arg(_context->precision().avg, 0, 'f', 2));
        _infoMetricTop1->setText(QString::number(_context->top1().avg, 'f', 2));
        _infoMetricTop5->setText(QString::number(_context->top5().avg, 'f', 2));

        double accuracyDelta = ir.accuracyDelta();
        if (accuracyDelta > _worstAccuracyDelta) {
            _worstAccuracyDelta = accuracyDelta;
            _worstPredictedImage->loadImage(ir.imageFile);
            _worstPredictedImage->setToolTip(QString(QStringLiteral("%1\nTop1: %2\nCorrect: %3"))
                                             .arg(ir.imageFile)
                                             .arg(ir.predictions[0].str())
                                             .arg(ir.findCorrect()->str()));
        }
        _lastUpdateMs = curTimeMs;
    }
}

void ResultsPanel::resetInfo() {
    _infoImagesPerSec->setText("N/A");
    _infoPrecision->setText("N/A");
    _infoMetricTop1->setText("N/A");
    _infoMetricTop5->setText("N/A");
    _worstAccuracyDelta = 0;
    _worstPredictedImage->clearImage();
    _worstPredictedImage->setToolTip("");
    _lastUpdateMs = 0;
    _infoNav->setText("");
}

void ResultsPanel::updateOnModeChanged(Mode mode) {
    bool v = mode.type == Mode::Type::CLASSIFICATION;
    _panelMetrics->setVisible(v);
    _panelWorstPrediction->setVisible(v);
    _panelPrecision->setVisible(!v);
    _panelZoom->setVisible(!v);
    _panelNav->setVisible(!v);
}

void ResultsPanel::updateOnEffectiveZoomChanged(double z) {
    int p = z * 100;
    _infoZoom->setText(QString("%1%").arg(p));
}
<|endoftext|>


<commit_before>/* errors.c - error reporting */

/*
 * This file is part of Playslave-C++.
 * Playslave-C++ is licenced under MIT License. See LICENSE.txt for more details.
 */

#ifndef CUPPA_ERRORS_H
#define CUPPA_ERRORS_H

#include <string>
#include <iostream>

/* Categories of error.
 */
enum class ErrorCode {
	OK,	// No error
	NO_FILE, // Tried to read nonexistent file
	BAD_STATE, // State transition not allowed
	BAD_COMMAND, // Command was malformed
	COMMAND_REJECTED, // Command was valid but refused
	COMMAND_IGNORED, // Command was silently ignored
	BAD_FILE, // Tried to read corrupt file
	BAD_CONFIG, // Program improperly configured
	AUDIO_INIT_FAIL, // Couldn't open audio backend
	INTERNAL_ERROR,	// General system error, usually fatal
	NO_MEM,	// Allocation of memory failed
	END_OF_FILE, // Reached end of file while reading
	INCOMPLETE,	// Incomplete computation, try again
	UNKNOWN, // Unknown error
};

class Error {
public:
	Error(ErrorCode error_code, std::string message);

	void ToResponse();
	ErrorCode Code();
	const std::string &Message();
private:
	ErrorCode error_code;
	std::string message;
};

inline void DebugArgs()
{
}

template<typename T1, typename... Ts>
inline void DebugArgs(T1 &t1, Ts &...ts)
{
	std::cerr << " " << t1;
	DebugArgs(ts...);
}

template<typename... Ts>
inline void Debug(Ts &...ts)
{
	std::cerr << "DEBUG:";
	DebugArgs(ts...);
	std::cerr << std::endl;
}

#endif				/* !CUPPA_ERRORS_H */
<commit_msg>Re-format errors.hpp.<commit_after>/* errors.c - error reporting */

/*
 * This file is part of Playslave-C++.
 * Playslave-C++ is licenced under MIT License. See LICENSE.txt for more
 * details.
 */

#ifndef CUPPA_ERRORS_H
#define CUPPA_ERRORS_H

#include <string>
#include <iostream>

/* Categories of error.
 */
enum class ErrorCode {
	OK,               // No error
	NO_FILE,          // Tried to read nonexistent file
	BAD_STATE,        // State transition not allowed
	BAD_COMMAND,      // Command was malformed
	COMMAND_REJECTED, // Command was valid but refused
	COMMAND_IGNORED,  // Command was silently ignored
	BAD_FILE,         // Tried to read corrupt file
	BAD_CONFIG,       // Program improperly configured
	AUDIO_INIT_FAIL,  // Couldn't open audio backend
	INTERNAL_ERROR,   // General system error, usually fatal
	NO_MEM,           // Allocation of memory failed
	END_OF_FILE,      // Reached end of file while reading
	INCOMPLETE,       // Incomplete computation, try again
	UNKNOWN,          // Unknown error
};

class Error {
public:
	Error(ErrorCode error_code, std::string message);

	void ToResponse();
	ErrorCode Code();
	const std::string &Message();

private:
	ErrorCode error_code;
	std::string message;
};

inline void DebugArgs()
{
}

template <typename T1, typename... Ts>
inline void DebugArgs(T1 &t1, Ts &... ts)
{
	std::cerr << " " << t1;
	DebugArgs(ts...);
}

template <typename... Ts>
inline void Debug(Ts &... ts)
{
	std::cerr << "DEBUG:";
	DebugArgs(ts...);
	std::cerr << std::endl;
}

#endif /* !CUPPA_ERRORS_H */
<|endoftext|>


<commit_before>// $Id$
// Main authors: Matevz Tadel & Alja Mrak-Tadel: 2006, 2007

/**************************************************************************
 * Copyright(c) 1998-2008, ALICE Experiment at CERN, all rights reserved. *
 * See http://aliceinfo.cern.ch/Offline/AliRoot/License.html for          *
 * full copyright notice.                                                 *
 **************************************************************************/
// ---------------------------------------------------------------------- //
void pmd_raw(Int_t mode = 0)
{
  gStyle->SetPalette(1, 0);

  TObjArray *pmdddlcont = new TObjArray();

  TString spl;

  TString sddl;
  TString bsddl="DDL";

  Int_t ievt = 0;
  AliRawReaderRoot reader("raw.root",ievt);
  AliPMDRawStream stream(&reader);

  gEve->DisableRedraw();

  TEveElementList* l = new TEveElementList("PMD");
  //  l->SetTitle("PMD");
  //  l->SetMainColor((Color_t)3);
  gEve->AddElement(l);

  Int_t NSM       = 0;
  Int_t istartDDL = 0;
  Int_t iendDDL   = 0;
  Int_t modnumber = 0;
  Int_t istartPlane = 0;
  Int_t iendPlane   = 0;
  Float_t zpos      = 0;

  switch(mode)
    {
    case 0:
      istartPlane = 0;
      iendPlane   = 1;
      printf("--- Visualization is set for PREshower Plane ---\n");
      break;

    case 1:
      istartPlane = 1;
      iendPlane   = 2;
      printf("--- Visualization is set for CPV Plane ---\n");
      break;

    case 2:
      istartPlane = 0;
      iendPlane   = 2;
      printf("--- Visualization is set for both the Plane ---\n");
      break;

    default:
      printf("--- Not set for any Plane ---\n");
    }

  for (Int_t ipl = istartPlane; ipl < iendPlane; ipl++)
    {

      if (ipl == 0)
	{
	  spl       = "PRE";
	  istartDDL = 0;
	  iendDDL   = 4;
	  zpos      = 365.;
	}
      if (ipl == 1)
	{
	  spl = "CPV";
	  istartDDL = 4;
	  iendDDL   = 6;
	  zpos      = 360.;
	}

      TEveElementList* lplane = new TEveElementList(spl.Data());
      //  l->SetMainColor((Color_t)3);
      gEve->AddElement(lplane, l);

      for (Int_t iddl = istartDDL; iddl < iendDDL; iddl++)
      //for (Int_t iddl = 0; iddl < 1; iddl++)
	{
	  sddl = bsddl;
	  sddl += iddl;
	  TEveElementList* lddl = new TEveElementList(sddl.Data());
	  //  l->SetMainColor((Color_t)3);
	  gEve->AddElement(ddl, lplane);

	  modnumber = iddl*6;

	  if (iddl < 4)
	    {
	      NSM = 6;
	    }
	  else if (iddl >=4 && iddl < 6)
	    {
	      NSM = 12;
	    }

	  reader.Select("PMD", iddl, iddl);
	  Bool_t junk = stream.DdlData(iddl,pmdddlcont);

	  for (Int_t ism = 0; ism < NSM; ism++)
	    {
	      AliEvePMDModule *lmodule = new AliEvePMDModule();
	      lmodule->SetPosition(0.,0.,zpos);
	      lmodule->DisplayRawData(modnumber,pmdddlcont);
	      gEve->AddElement(lmodule, lddl);
	      modnumber++;
	      if (iddl == 4 && modnumber == 30) modnumber = 42;
	    }

	  pmdddlcont->Clear();
	}
    }

  gEve->EnableRedraw();
}

// ---------------------------------------------------------------------- //
<commit_msg>From Basanta: I have modified the AliPMDRawStream file which needs little modification<commit_after>// $Id$
// Main authors: Matevz Tadel & Alja Mrak-Tadel: 2006, 2007

/**************************************************************************
 * Copyright(c) 1998-2008, ALICE Experiment at CERN, all rights reserved. *
 * See http://aliceinfo.cern.ch/Offline/AliRoot/License.html for          *
 * full copyright notice.                                                 *
 **************************************************************************/
// ---------------------------------------------------------------------- //
void pmd_raw(Int_t mode = 0)
{
  gStyle->SetPalette(1, 0);

  TObjArray *pmdddlcont = new TObjArray();

  TString spl;

  TString sddl;
  TString bsddl="DDL";

  Int_t ievt = 0;
  AliRawReaderRoot reader("raw.root",ievt);
  AliPMDRawStream stream(&reader);

  gEve->DisableRedraw();

  TEveElementList* l = new TEveElementList("PMD");
  //  l->SetTitle("PMD");
  //  l->SetMainColor((Color_t)3);
  gEve->AddElement(l);

  Int_t NSM       = 0;
  Int_t istartDDL = 0;
  Int_t iendDDL   = 0;
  Int_t modnumber = 0;
  Int_t istartPlane = 0;
  Int_t iendPlane   = 0;
  Float_t zpos      = 0;

  switch(mode)
    {
    case 0:
      istartPlane = 0;
      iendPlane   = 1;
      printf("--- Visualization is set for PREshower Plane ---\n");
      break;

    case 1:
      istartPlane = 1;
      iendPlane   = 2;
      printf("--- Visualization is set for CPV Plane ---\n");
      break;

    case 2:
      istartPlane = 0;
      iendPlane   = 2;
      printf("--- Visualization is set for both the Plane ---\n");
      break;

    default:
      printf("--- Not set for any Plane ---\n");
    }

  for (Int_t ipl = istartPlane; ipl < iendPlane; ipl++)
    {

      if (ipl == 0)
	{
	  spl       = "PRE";
	  istartDDL = 0;
	  iendDDL   = 4;
	  zpos      = 365.;
	}
      if (ipl == 1)
	{
	  spl = "CPV";
	  istartDDL = 4;
	  iendDDL   = 6;
	  zpos      = 360.;
	}

      TEveElementList* lplane = new TEveElementList(spl.Data());
      //  l->SetMainColor((Color_t)3);
      gEve->AddElement(lplane, l);

      Int_t iddl = -1;

      while ((iddl = rawStream.DdlData(&pmdddlcont)) >=0) {
	  if (iddl >= istartDDL && iddl < iendDDL){
	      sddl = bsddl;
	      sddl += iddl;
	      TEveElementList* lddl = new TEveElementList(sddl.Data());
	      //  l->SetMainColor((Color_t)3);
	      gEve->AddElement(ddl, lplane);

	      modnumber = iddl*6;

	      if (iddl < 4)
	      {
		  NSM = 6;
	      }
	      else if (iddl >=4 && iddl < 6)
	      {
		  NSM = 12;
	      }

	      for (Int_t ism = 0; ism < NSM; ism++)
	      {
		  AliEvePMDModule *lmodule = new AliEvePMDModule();
		  lmodule->SetPosition(0.,0.,zpos);
		  lmodule->DisplayRawData(modnumber,pmdddlcont);
		  gEve->AddElement(lmodule, lddl);
		  modnumber++;
		  if (iddl == 4 && modnumber == 30) modnumber = 42;
	      }

	      pmdddlcont->Clear();
	  }
      }

      gEve->EnableRedraw();
    }

}
// ---------------------------------------------------------------------- //

<|endoftext|>


<commit_before>/* BEGIN_COMMON_COPYRIGHT_HEADER
 * (c)LGPL2+
 *
 * LXQt - a lightweight, Qt based, desktop toolset
 * https://lxqt.org
 *
 * Copyright: 2011 Razor team
 * Authors:
 *   Maciej Płaza <plaza.maciej@gmail.com>
 *
 * This program or library is free software; you can redistribute it
 * and/or modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.

 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA
 *
 * END_COMMON_COPYRIGHT_HEADER */

#include "lxqtcpuloadconfiguration.h"
#include "ui_lxqtcpuloadconfiguration.h"

#define BAR_ORIENT_BOTTOMUP "bottomUp"
#define BAR_ORIENT_TOPDOWN "topDown"
#define BAR_ORIENT_LEFTRIGHT "leftRight"
#define BAR_ORIENT_RIGHTLEFT "rightLeft"

LXQtCpuLoadConfiguration::LXQtCpuLoadConfiguration(PluginSettings *settings, QWidget *parent) :
    LXQtPanelPluginConfigDialog(settings, parent),
    ui(new Ui::LXQtCpuLoadConfiguration)
{
    setAttribute(Qt::WA_DeleteOnClose);
    setObjectName(QStringLiteral("CpuLoadConfigurationWindow"));
    ui->setupUi(this);

    fillBarOrientations();

    connect(ui->buttons, SIGNAL(clicked(QAbstractButton*)),
            this, SLOT(dialogButtonsAction(QAbstractButton*)));

    loadSettings();

    connect(ui->showTextCB, SIGNAL(toggled(bool)),
            this, SLOT(showTextChanged(bool)));
    connect(ui->barWidthSB, SIGNAL(valueChanged(int)),
            this, SLOT(barWidthChanged(int)));
    connect(ui->updateIntervalSpinBox, SIGNAL(valueChanged(double)),
            this, SLOT(updateIntervalChanged(double)));
    connect(ui->barOrientationCOB, SIGNAL(currentIndexChanged(int)),
            this, SLOT(barOrientationChanged(int)));
}

LXQtCpuLoadConfiguration::~LXQtCpuLoadConfiguration()
{
    delete ui;
}

void LXQtCpuLoadConfiguration::fillBarOrientations()
{
    ui->barOrientationCOB->addItem(trUtf8("Bottom up"), QStringLiteral(BAR_ORIENT_BOTTOMUP));
    ui->barOrientationCOB->addItem(trUtf8("Top down"), QStringLiteral(BAR_ORIENT_TOPDOWN));
    ui->barOrientationCOB->addItem(trUtf8("Left to right"), QStringLiteral(BAR_ORIENT_LEFTRIGHT));
    ui->barOrientationCOB->addItem(trUtf8("Right to left"), QStringLiteral(BAR_ORIENT_RIGHTLEFT));
}

void LXQtCpuLoadConfiguration::loadSettings()
{
    ui->showTextCB->setChecked(settings().value(QStringLiteral("showText"), false).toBool());
    ui->barWidthSB->setValue(settings().value(QStringLiteral("barWidth"), 20).toInt());
    ui->updateIntervalSpinBox->setValue(settings().value(QStringLiteral("updateInterval"), 1000).toInt() / 1000.0);

    int boIndex = ui->barOrientationCOB->findData(
            settings().value(QStringLiteral("barOrientation"), QStringLiteral(BAR_ORIENT_BOTTOMUP)));
    boIndex = (boIndex < 0) ? 1 : boIndex;
    ui->barOrientationCOB->setCurrentIndex(boIndex);

//	QString menuFile = settings().value("menu_file", "").toString();
//	if (menuFile.isEmpty())
//	{
//		menuFile = XdgMenu::getMenuFileName();
//	}
//	ui->menuFilePathLE->setText(menuFile);
//	ui->shortcutEd->setKeySequence(settings().value("shortcut", "Alt+F1").toString());
}

void LXQtCpuLoadConfiguration::showTextChanged(bool value)
{
    settings().setValue(QStringLiteral("showText"), value);
}

void LXQtCpuLoadConfiguration::barWidthChanged(int value)
{
    settings().setValue(QStringLiteral("barWidth"), value);
}

void LXQtCpuLoadConfiguration::updateIntervalChanged(double value)
{
    settings().setValue(QStringLiteral("updateInterval"), value*1000);
}

void LXQtCpuLoadConfiguration::barOrientationChanged(int index)
{
    settings().setValue(QStringLiteral("barOrientation"), ui->barOrientationCOB->itemData(index).toString());
}
<commit_msg>Remove deprecated trUtf8()<commit_after>/* BEGIN_COMMON_COPYRIGHT_HEADER
 * (c)LGPL2+
 *
 * LXQt - a lightweight, Qt based, desktop toolset
 * https://lxqt.org
 *
 * Copyright: 2011 Razor team
 * Authors:
 *   Maciej Płaza <plaza.maciej@gmail.com>
 *
 * This program or library is free software; you can redistribute it
 * and/or modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.

 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA
 *
 * END_COMMON_COPYRIGHT_HEADER */

#include "lxqtcpuloadconfiguration.h"
#include "ui_lxqtcpuloadconfiguration.h"

#define BAR_ORIENT_BOTTOMUP "bottomUp"
#define BAR_ORIENT_TOPDOWN "topDown"
#define BAR_ORIENT_LEFTRIGHT "leftRight"
#define BAR_ORIENT_RIGHTLEFT "rightLeft"

LXQtCpuLoadConfiguration::LXQtCpuLoadConfiguration(PluginSettings *settings, QWidget *parent) :
    LXQtPanelPluginConfigDialog(settings, parent),
    ui(new Ui::LXQtCpuLoadConfiguration)
{
    setAttribute(Qt::WA_DeleteOnClose);
    setObjectName(QStringLiteral("CpuLoadConfigurationWindow"));
    ui->setupUi(this);

    fillBarOrientations();

    connect(ui->buttons, SIGNAL(clicked(QAbstractButton*)),
            this, SLOT(dialogButtonsAction(QAbstractButton*)));

    loadSettings();

    connect(ui->showTextCB, SIGNAL(toggled(bool)),
            this, SLOT(showTextChanged(bool)));
    connect(ui->barWidthSB, SIGNAL(valueChanged(int)),
            this, SLOT(barWidthChanged(int)));
    connect(ui->updateIntervalSpinBox, SIGNAL(valueChanged(double)),
            this, SLOT(updateIntervalChanged(double)));
    connect(ui->barOrientationCOB, SIGNAL(currentIndexChanged(int)),
            this, SLOT(barOrientationChanged(int)));
}

LXQtCpuLoadConfiguration::~LXQtCpuLoadConfiguration()
{
    delete ui;
}

void LXQtCpuLoadConfiguration::fillBarOrientations()
{
    ui->barOrientationCOB->addItem(tr("Bottom up"), QStringLiteral(BAR_ORIENT_BOTTOMUP));
    ui->barOrientationCOB->addItem(tr("Top down"), QStringLiteral(BAR_ORIENT_TOPDOWN));
    ui->barOrientationCOB->addItem(tr("Left to right"), QStringLiteral(BAR_ORIENT_LEFTRIGHT));
    ui->barOrientationCOB->addItem(tr("Right to left"), QStringLiteral(BAR_ORIENT_RIGHTLEFT));
}

void LXQtCpuLoadConfiguration::loadSettings()
{
    ui->showTextCB->setChecked(settings().value(QStringLiteral("showText"), false).toBool());
    ui->barWidthSB->setValue(settings().value(QStringLiteral("barWidth"), 20).toInt());
    ui->updateIntervalSpinBox->setValue(settings().value(QStringLiteral("updateInterval"), 1000).toInt() / 1000.0);

    int boIndex = ui->barOrientationCOB->findData(
            settings().value(QStringLiteral("barOrientation"), QStringLiteral(BAR_ORIENT_BOTTOMUP)));
    boIndex = (boIndex < 0) ? 1 : boIndex;
    ui->barOrientationCOB->setCurrentIndex(boIndex);

//	QString menuFile = settings().value("menu_file", "").toString();
//	if (menuFile.isEmpty())
//	{
//		menuFile = XdgMenu::getMenuFileName();
//	}
//	ui->menuFilePathLE->setText(menuFile);
//	ui->shortcutEd->setKeySequence(settings().value("shortcut", "Alt+F1").toString());
}

void LXQtCpuLoadConfiguration::showTextChanged(bool value)
{
    settings().setValue(QStringLiteral("showText"), value);
}

void LXQtCpuLoadConfiguration::barWidthChanged(int value)
{
    settings().setValue(QStringLiteral("barWidth"), value);
}

void LXQtCpuLoadConfiguration::updateIntervalChanged(double value)
{
    settings().setValue(QStringLiteral("updateInterval"), value*1000);
}

void LXQtCpuLoadConfiguration::barOrientationChanged(int index)
{
    settings().setValue(QStringLiteral("barOrientation"), ui->barOrientationCOB->itemData(index).toString());
}
<|endoftext|>


<commit_before>#include "chip8.hh"

static uint8_t default_char[80] =
{
    0xF0 ,0x90, 0x90, 0x90, 0xF0, //0
    0x20, 0x60, 0x20, 0x20, 0x70, //1
    0xF0, 0x10, 0xF0, 0x80, 0xF0, //2
    0xF0, 0x10, 0xF0, 0x10, 0xF0, //3
    0x90, 0x90, 0xF0, 0x10, 0x10, //4
    0xF0, 0x80, 0xF0, 0x10, 0xF0, //5
    0xF0, 0x80, 0xF0, 0x90, 0xF0, //6
    0xF0, 0x10, 0x20, 0x40, 0x40, //7
    0xF0, 0x90, 0xF0, 0x90, 0xF0, //8
    0xF0, 0x90, 0xF0, 0x10, 0xF0, //9
    0xF0, 0x90, 0xF0, 0x90, 0x90, //A
    0xE0, 0x90, 0xE0, 0x90, 0xE0, //B
    0xF0, 0x80, 0x80, 0x80, 0xF0, //C
    0xE0, 0x90, 0x90, 0x90, 0xE0, //D
    0xF0, 0x80, 0xF0, 0x80, 0xF0, //E
    0xF0, 0x80, 0xF0, 0x80, 0x80  //F
};

Chip8::Chip8()
    : error_(0)
    , pc_(0x200)
    , sp_(0)
    , I_(0)
    , dt_(0)
    , st_(0)
{}

Chip8::~Chip8()
{
    SDL_FreeSurface(pixel_);
    SDL_Quit();
}

void Chip8::init()
{
    if (SDL_Init(SDL_INIT_VIDEO) == -1)
    {
        std::cerr << "Error cannot initialize SDL" << std::endl;
        error_ = 2;
    }

    // Initialise memory to 0
    memset(&ram_, 0, 4096);
    memset(&V_, 0, 16);
    memset(&stack_, 0, 16 * 2);
    memset(&vga_mem_, 0, 64 * 32);

    for (size_t i = 0; i < 80; ++i)
        ram_[i] = default_char[i];

    pixel_ = SDL_CreateRGBSurface(0, 10, 10, 32, 0, 0, 0, 0);

    SDL_FillRect(pixel_, NULL, SDL_MapRGB(pixel_->format, 255, 255, 255));
}

void Chip8::load_bin(const std::string& path)
{
    std::ifstream file;
    size_t file_size;

    file.open(path, std::ios::in | std::ios::binary);

    if (file.is_open())
    {
        file.seekg(0, std::ios::end);
        file_size = file.tellg();

        // Test if the ROM will feet in RAM
        if (file_size > 0xFFF - 0x200)
        {
            std::cerr << "Error ROM cannot feet in RAM" << std::endl;
            error_ = 4;
        }
        else // OK
        {
            char* data_rom = (char* )(&(ram_[0x200]));

            file.seekg(0, std::ios::beg);
            file.read(data_rom, file_size);
        }

        file.close();
    }
    else
    {
        std::cerr << "Error while opening the ROM" << std::endl;
        error_ = 3;
    }
}

void Chip8::render(SDL_Surface* screen)
{
    SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 0, 0, 0));

    SDL_Rect pixel_pos;

    for (size_t x = 0; x < 64; ++x)
    {
        for (size_t y = 0; y < 32; ++y)
        {
            if (vga_mem_[y * 64 + x] == 1)
            {
                pixel_pos.x = x * 10;
                pixel_pos.y = y * 10;

                SDL_BlitSurface(pixel_, NULL, screen, &pixel_pos);
            }
        }
    }

    SDL_Flip(screen);
}

void Chip8::execute()
{
    int loop = 1;
    SDL_Event event;

    SDL_Surface* screen = SDL_SetVideoMode(640, 320, 32, SDL_HWSURFACE);
    SDL_WM_SetCaption("Chip8 Emulator", NULL);

    while (!error_ && loop)
    {
        SDL_PollEvent(&event);

        switch (event.type)
        {
            case SDL_QUIT:
                loop = 0;
        }

        // Execute next instruction
        execute_next();

        render(screen);
    }
}

void Chip8::execute_next()
{
    // Fetch opcode
    uint16_t op = (ram_[pc_] << 0x8) | ram_[pc_ + 1];

    switch (op & 0xF000)
    {
        case 0x0000:
            switch (op & 0x00FF)
            {
                case 0x00E0: // CLS
                    memset(&vga_mem_, 0, 64 * 32);
                    pc_ += 2;
                    break;
                case 0x00EE: // RET
                    fault(op);
                    break;
                default: // JP ADDR
                    // -1 to avoid +1 at the end of the switch
                    pc_ = op & 0x0FFF;
                    break;
            }
            break;
        case 0x2000: // Call addr
            {
                uint16_t addr = op & 0x0FFF;

                stack_[sp_++] = pc_;

                pc_ = addr;
            }
            break;
        case 0x4000: // NE Vx, byte
            {
                uint16_t x = op & 0x0F00;
                uint16_t byte = op & 0x00FF;

                if (V_[x] != byte)
                    pc_ += 2;

                pc_ += 2;
            }
            break;
        case 0x6000: // LD Vx, byte
            {
                uint16_t x = op & 0x0F00;
                uint16_t byte = op & 0x00FF;

                x = x >> 0x8;

                V_[x] = byte;

                pc_ += 2;
                break;
            }
            break;
        case 0x8000:
            {
                uint16_t x = (op & 0x0F00) >> 0x8;
                uint16_t y = (op & 0x00F0) >> 0x4;

                switch (op & 0x000F)
                {
                    case 0x0007: //SUBN Vx, Vy

                        if (V_[y] > V_[x])
                            V_[0xF] = 0x1;
                        else
                            V_[0xF] = 0x0;

                        V_[x] = V_[y] - V_[x];

                        pc_ += 2;
                        break;
                    default:
                        fault(op);
                        break;
                }
            }
            break;
        case 0xA000: // LD I, addr
            {
                I_ = (op & 0x0FFF);

                pc_ += 2;
            }
            break;
        case 0xD000: // DRW Vx, Vy, nibble
            {
                uint16_t x = V_[(op & 0x0F00) >> 0x8];
                uint16_t y = V_[(op & 0x00F0) >> 0x4];
                uint16_t nibble = (op & 0x000F);
                uint16_t pixel;

                V_[0xF] = 0;

                for (size_t i = 0; i < nibble; ++i)
                {
                    pixel = ram_[I_ + i];

                    for (size_t j = 0; j < 8; ++j)
                    {
                        if ((pixel & (0x80 >> j)) != 0)
                        {
                            if (vga_mem_[x + j + ((y + i) * 64)] != 0)
                                V_[0xF] = 1;

                            vga_mem_[x + j + ((y + i) * 64)] ^= 1;
                        }
                    }

                }

                pc_ += 2;
            }
            break;
        case 0xF000:
            switch (op & 0x00FF)
            {
                case 0x0033: //LD B, Vx
                    {
                        uint16_t x = (op & 0x0F00) >> 0x8;
                        uint8_t tmp = V_[x] % 100;

                        ram_[I_] = V_[x] / 100;
                        ram_[I_ + 1] = tmp / 10;
                        ram_[I_ + 2] = tmp % 10;

                        pc_ += 2;
                    }
                    break;
                default:
                    fault(op);
                    break;
            }
            break;
        default:
            fault(op);
            break;
    }

    if (dt_ > 0)
        --dt_;

    if (st_ > 0)
        --st_;
}

void Chip8::fault(uint16_t op)
{
    std::cerr << "CPU Fault" << std::endl;
    std::cerr << "Error unknown instruction "
              << std::hex << std::setfill('0') << std::setw(4)
              << std::uppercase << op << std::endl;
    dump();
    error_ = 5;
}

void Chip8::dump()
{
    std::cerr << "Dumping RAM" << std::endl;

    for (size_t i = 0; i < 2048; ++i)
    {
        if (i % 16 == 0)
            std::cerr << std::endl << "0x" << std::setfill('0') << std::setw(3)
                      << std::uppercase << std::hex << i << " | ";

        std::cerr << std::hex << std::setfill('0') << std::setw(2)
                  << std::uppercase << int(ram_[i])
                  << std::uppercase << std::setfill('0') << std::setw(2)
                  << int(ram_[i + 1]) << " ";
    }

    std::cerr << std::endl;

    std::cerr << std::endl << "Dumping Register" << std::endl;

    std::cerr << std::endl << "PC: 0x" << std::hex << std::setfill('0')
              << std::setw(4) << int(pc_) << std::endl;

    std::cerr << "I: 0x" << std::hex << std::setfill('0')
              << std::setw(4) << int(I_) << std::endl;

    std::cerr << "SP: 0x" << std::hex << std::setfill('0')
              << std::setw(2) << int(sp_) << std::endl;

    std::cerr << "DT: 0x" << std::hex << std::setfill('0')
              << std::setw(2) << int(dt_) << std::endl;

    std::cerr << "ST: 0x" << std::hex << std::setfill('0')
              << std::setw(2) << int(st_) << std::endl;

    for (size_t i = 0; i < 16; ++i)
    {
        std::cerr << "V" << i << ": 0x" << std::hex << std::setfill('0')
                  << std::setw(2) << int(V_[i]) << std::endl;
    }

    std::cerr << std::endl << "Dumping Stack" << std::endl;

    std::cerr << std::endl;

    for (size_t i = 0; i < 16; ++i)
    {
        std::cerr << "0x" << std::hex << std::setfill('0')
                  << std::setw(4) << int(stack_[i]) << std::endl;
    }
}

int Chip8::get_error()
{
    return error_;
}
<commit_msg>Add Fx65 instruction (LD [I], Vx)<commit_after>#include "chip8.hh"

static uint8_t default_char[80] =
{
    0xF0 ,0x90, 0x90, 0x90, 0xF0, //0
    0x20, 0x60, 0x20, 0x20, 0x70, //1
    0xF0, 0x10, 0xF0, 0x80, 0xF0, //2
    0xF0, 0x10, 0xF0, 0x10, 0xF0, //3
    0x90, 0x90, 0xF0, 0x10, 0x10, //4
    0xF0, 0x80, 0xF0, 0x10, 0xF0, //5
    0xF0, 0x80, 0xF0, 0x90, 0xF0, //6
    0xF0, 0x10, 0x20, 0x40, 0x40, //7
    0xF0, 0x90, 0xF0, 0x90, 0xF0, //8
    0xF0, 0x90, 0xF0, 0x10, 0xF0, //9
    0xF0, 0x90, 0xF0, 0x90, 0x90, //A
    0xE0, 0x90, 0xE0, 0x90, 0xE0, //B
    0xF0, 0x80, 0x80, 0x80, 0xF0, //C
    0xE0, 0x90, 0x90, 0x90, 0xE0, //D
    0xF0, 0x80, 0xF0, 0x80, 0xF0, //E
    0xF0, 0x80, 0xF0, 0x80, 0x80  //F
};

Chip8::Chip8()
    : error_(0)
    , pc_(0x200)
    , sp_(0)
    , I_(0)
    , dt_(0)
    , st_(0)
{}

Chip8::~Chip8()
{
    SDL_FreeSurface(pixel_);
    SDL_Quit();
}

void Chip8::init()
{
    if (SDL_Init(SDL_INIT_VIDEO) == -1)
    {
        std::cerr << "Error cannot initialize SDL" << std::endl;
        error_ = 2;
    }

    // Initialise memory to 0
    memset(&ram_, 0, 4096);
    memset(&V_, 0, 16);
    memset(&stack_, 0, 16 * 2);
    memset(&vga_mem_, 0, 64 * 32);

    for (size_t i = 0; i < 80; ++i)
        ram_[i] = default_char[i];

    pixel_ = SDL_CreateRGBSurface(0, 10, 10, 32, 0, 0, 0, 0);

    SDL_FillRect(pixel_, NULL, SDL_MapRGB(pixel_->format, 255, 255, 255));
}

void Chip8::load_bin(const std::string& path)
{
    std::ifstream file;
    size_t file_size;

    file.open(path, std::ios::in | std::ios::binary);

    if (file.is_open())
    {
        file.seekg(0, std::ios::end);
        file_size = file.tellg();

        // Test if the ROM will feet in RAM
        if (file_size > 0xFFF - 0x200)
        {
            std::cerr << "Error ROM cannot feet in RAM" << std::endl;
            error_ = 4;
        }
        else // OK
        {
            char* data_rom = (char* )(&(ram_[0x200]));

            file.seekg(0, std::ios::beg);
            file.read(data_rom, file_size);
        }

        file.close();
    }
    else
    {
        std::cerr << "Error while opening the ROM" << std::endl;
        error_ = 3;
    }
}

void Chip8::render(SDL_Surface* screen)
{
    SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 0, 0, 0));

    SDL_Rect pixel_pos;

    for (size_t x = 0; x < 64; ++x)
    {
        for (size_t y = 0; y < 32; ++y)
        {
            if (vga_mem_[y * 64 + x] == 1)
            {
                pixel_pos.x = x * 10;
                pixel_pos.y = y * 10;

                SDL_BlitSurface(pixel_, NULL, screen, &pixel_pos);
            }
        }
    }

    SDL_Flip(screen);
}

void Chip8::execute()
{
    int loop = 1;
    SDL_Event event;

    SDL_Surface* screen = SDL_SetVideoMode(640, 320, 32, SDL_HWSURFACE);
    SDL_WM_SetCaption("Chip8 Emulator", NULL);

    while (!error_ && loop)
    {
        SDL_PollEvent(&event);

        switch (event.type)
        {
            case SDL_QUIT:
                loop = 0;
        }

        // Execute next instruction
        execute_next();

        render(screen);
    }
}

void Chip8::execute_next()
{
    // Fetch opcode
    uint16_t op = (ram_[pc_] << 0x8) | ram_[pc_ + 1];

    switch (op & 0xF000)
    {
        case 0x0000:
            switch (op & 0x00FF)
            {
                case 0x00E0: // CLS
                    memset(&vga_mem_, 0, 64 * 32);
                    pc_ += 2;
                    break;
                case 0x00EE: // RET
                    fault(op);
                    break;
                default: // JP ADDR
                    // -1 to avoid +1 at the end of the switch
                    pc_ = op & 0x0FFF;
                    break;
            }
            break;
        case 0x2000: // Call addr
            {
                uint16_t addr = op & 0x0FFF;

                stack_[sp_++] = pc_;

                pc_ = addr;
            }
            break;
        case 0x4000: // NE Vx, byte
            {
                uint16_t x = op & 0x0F00;
                uint16_t byte = op & 0x00FF;

                if (V_[x] != byte)
                    pc_ += 2;

                pc_ += 2;
            }
            break;
        case 0x6000: // LD Vx, byte
            {
                uint16_t x = op & 0x0F00;
                uint16_t byte = op & 0x00FF;

                x = x >> 0x8;

                V_[x] = byte;

                pc_ += 2;
                break;
            }
            break;
        case 0x8000:
            {
                uint16_t x = (op & 0x0F00) >> 0x8;
                uint16_t y = (op & 0x00F0) >> 0x4;

                switch (op & 0x000F)
                {
                    case 0x0007: //SUBN Vx, Vy

                        if (V_[y] > V_[x])
                            V_[0xF] = 0x1;
                        else
                            V_[0xF] = 0x0;

                        V_[x] = V_[y] - V_[x];

                        pc_ += 2;
                        break;
                    default:
                        fault(op);
                        break;
                }
            }
            break;
        case 0xA000: // LD I, addr
            {
                I_ = (op & 0x0FFF);

                pc_ += 2;
            }
            break;
        case 0xD000: // DRW Vx, Vy, nibble
            {
                uint16_t x = V_[(op & 0x0F00) >> 0x8];
                uint16_t y = V_[(op & 0x00F0) >> 0x4];
                uint16_t nibble = (op & 0x000F);
                uint16_t pixel;

                V_[0xF] = 0;

                for (size_t i = 0; i < nibble; ++i)
                {
                    pixel = ram_[I_ + i];

                    for (size_t j = 0; j < 8; ++j)
                    {
                        if ((pixel & (0x80 >> j)) != 0)
                        {
                            if (vga_mem_[x + j + ((y + i) * 64)] != 0)
                                V_[0xF] = 1;

                            vga_mem_[x + j + ((y + i) * 64)] ^= 1;
                        }
                    }

                }

                pc_ += 2;
            }
            break;
        case 0xF000:
            switch (op & 0x00FF)
            {
                case 0x0033: // LD B, Vx
                    {
                        uint16_t x = (op & 0x0F00) >> 0x8;
                        uint8_t tmp = V_[x] % 100;

                        ram_[I_] = V_[x] / 100;
                        ram_[I_ + 1] = tmp / 10;
                        ram_[I_ + 2] = tmp % 10;

                        pc_ += 2;
                    }
                    break;
                case 0x0065: // LD [I], Vx
                    {
                        uint16_t x = (op & 0x0F00) >> 0x8;

                        for (size_t i = 0; i <= x; ++i)
                            ram_[I_ + i] = V_[i];

                        pc_ += 2;
                    }
                    break;
                default:
                    fault(op);
                    break;
            }
            break;
        default:
            fault(op);
            break;
    }

    if (dt_ > 0)
        --dt_;

    if (st_ > 0)
        --st_;
}

void Chip8::fault(uint16_t op)
{
    std::cerr << "CPU Fault" << std::endl;
    std::cerr << "Error unknown instruction "
              << std::hex << std::setfill('0') << std::setw(4)
              << std::uppercase << op << std::endl;
    dump();
    error_ = 5;
}

void Chip8::dump()
{
    std::cerr << "Dumping RAM" << std::endl;

    for (size_t i = 0; i < 2048; ++i)
    {
        if (i % 16 == 0)
            std::cerr << std::endl << "0x" << std::setfill('0') << std::setw(3)
                      << std::uppercase << std::hex << i << " | ";

        std::cerr << std::hex << std::setfill('0') << std::setw(2)
                  << std::uppercase << int(ram_[i])
                  << std::uppercase << std::setfill('0') << std::setw(2)
                  << int(ram_[i + 1]) << " ";
    }

    std::cerr << std::endl;

    std::cerr << std::endl << "Dumping Register" << std::endl;

    std::cerr << std::endl << "PC: 0x" << std::hex << std::setfill('0')
              << std::setw(4) << int(pc_) << std::endl;

    std::cerr << "I: 0x" << std::hex << std::setfill('0')
              << std::setw(4) << int(I_) << std::endl;

    std::cerr << "SP: 0x" << std::hex << std::setfill('0')
              << std::setw(2) << int(sp_) << std::endl;

    std::cerr << "DT: 0x" << std::hex << std::setfill('0')
              << std::setw(2) << int(dt_) << std::endl;

    std::cerr << "ST: 0x" << std::hex << std::setfill('0')
              << std::setw(2) << int(st_) << std::endl;

    for (size_t i = 0; i < 16; ++i)
    {
        std::cerr << "V" << i << ": 0x" << std::hex << std::setfill('0')
                  << std::setw(2) << int(V_[i]) << std::endl;
    }

    std::cerr << std::endl << "Dumping Stack" << std::endl;

    std::cerr << std::endl;

    for (size_t i = 0; i < 16; ++i)
    {
        std::cerr << "0x" << std::hex << std::setfill('0')
                  << std::setw(4) << int(stack_[i]) << std::endl;
    }
}

int Chip8::get_error()
{
    return error_;
}
<|endoftext|>


<commit_before>/**
 ** \file scheduler/scheduler.cc
 ** \brief Implementation of scheduler::Scheduler.
 */

//#define ENABLE_DEBUG_TRACES

#include <cassert>

#include <libport/compiler.hh>
#include <libport/containers.hh>
#include <libport/foreach.hh>

#include "kernel/userver.hh"

#include "object/urbi-exception.hh"

#include "scheduler/scheduler.hh"
#include "scheduler/job.hh"

namespace scheduler
{

  // This function is required to start a new job using the libcoroutine.
  // Its only purpose is to create the context and start the execution
  // of the new job.
  static void
  run_job (void* job)
  {
    static_cast<Job*>(job)->run();
  }

  void
  Scheduler::add_job (Job* job)
  {
    assert (job);
    assert (!libport::has (jobs_, job));
    assert (!libport::has (jobs_to_start_, job));
    jobs_to_start_.push_back (job);
  }

  libport::utime_t
  Scheduler::work ()
  {
#ifdef ENABLE_DEBUG_TRACES
    static int cycle = 0;
#endif
    ECHO ("======================================================== cycle "
	  << ++cycle);

    // Start new jobs
    to_start_.clear ();
    std::swap (to_start_, jobs_to_start_);
    foreach (Job* job, to_start_)
    {
      assert (job);
      ECHO ("will start job " << *job);
      // Job will start for a very short time and do a yield_front() to
      // be restarted below in the course of the regular cycle.
      assert (!current_job_);
      current_job_ = job;
      Coro_startCoro_ (self_, job->coro_get(), job, run_job);
      // We have to assume that a new job may have had side-effects.
      possible_side_effect_ = true;
    }

    // Start deferred jobs
    for (libport::utime_t current_time = ::urbiserver->getTime ();
	 !deferred_jobs_.empty();
	 deferred_jobs_.pop ())
    {
      deferred_job j = deferred_jobs_.top ();
      if (current_time < j.get<0>())
	break;
      jobs_.push_back (j.get<1> ());
    }

    // If something is going to happen, or if we have just started a
    // new job, add the list of jobs waiting for something to happen
    // on the pending jobs queue.
    if (!if_change_jobs_.empty() && (possible_side_effect_ || !jobs_.empty()))
    {
      foreach (Job* job, if_change_jobs_)
	jobs_.push_back (job);
      if_change_jobs_.clear ();
    }

    // Run all the jobs in the run queue once. If any job declares upon entry or
    // return that it is not side-effect free, we remember that for the next
    // cycle.
    possible_side_effect_ = false;
    pending_.clear ();
    std::swap (pending_, jobs_);

    ECHO (pending_.size() << " jobs in the queue for this cycle");
    foreach (Job* job, pending_)
    {
      assert (job);
      assert (!job->terminated ());
      ECHO ("will resume job " << *job);
      possible_side_effect_ |= !job->side_effect_free_get ();
      Coro_switchTo_ (self_, job->coro_get ());
      possible_side_effect_ |= !job->side_effect_free_get ();
      ECHO ("back from job " << *job);
    }

    // Do we have some work to do now?
    if (!jobs_.empty () || !jobs_to_start_.empty())
    {
      ECHO ("scheduler: asking to be recalled ASAP, " << jobs_.size() << " jobs ready and " << jobs_to_start_.size()
	    << " to start");
      return 0;
    }

    // Do we have deferred jobs?
    if (!deferred_jobs_.empty ())
    {
      ECHO ("scheduler: asking to be recalled later");
      return deferred_jobs_.top ().get<0> ();
    }

    // Ok, let's say, we'll be called again in one hour.
    ECHO ("scheduler: asking to be recalled in a long time");
    return ::urbiserver->getTime() + 3600000000LL;
  }

  void
  Scheduler::switch_back (Job* job)
  {
    // Switch back to the scheduler.
    assert (current_job_ == job);
    current_job_ = 0;
    Coro_switchTo_ (job->coro_get (), self_);
    // We regained control, we are again in the context of the job.
    assert (!current_job_);
    current_job_ = job;
    ECHO ("job " << *job << " resumed");
    // Check that we are not near exhausting the stack space.
    if (Coro_stackSpaceAlmostGone (job->coro_get ()))
      throw object::StackExhaustedError ("stack space exhausted");
    // Execute a deferred exception if any
    job->check_for_pending_exception ();
  }

  void
  Scheduler::resume_scheduler (Job* job)
  {
    // If the job has not terminated, put it at the back of the run queue
    // so that the run queue order is preserved between work cycles.
    if (!job->terminated ())
      jobs_.push_back (job);
    ECHO (*job << " has " << (job->terminated () ? "" : "not ") << "terminated");
    switch_back (job);
  }

  void
  Scheduler::resume_scheduler_front (Job* job)
  {
    // Put the job in front of the queue. If the job asks to be requeued,
    // it is not terminated.
    assert (!job->terminated ());
    jobs_.push_front (job);
    switch_back (job);
  }

  void
  Scheduler::resume_scheduler_until (Job* job, libport::utime_t deadline)
  {
    // Put the job in the deferred queue. If the job asks to be requeued,
    // it is not terminated.
    assert (!job->terminated ());
    deferred_jobs_.push (boost::make_tuple (deadline, job));
    switch_back (job);
  }

  void
  Scheduler::resume_scheduler_suspend (Job* job)
  {
    suspended_jobs_.push_back (job);
    switch_back (job);
  }

  void
  Scheduler::resume_scheduler_things_changed (Job* job)
  {
    if_change_jobs_.push_back (job);
    switch_back (job);
  }

  void
  Scheduler::resume_job (Job* job)
  {
    // Suspended job may have been killed externally, in which case it
    // will not appear in the list of suspended jobs.

    if (libport::has (suspended_jobs_, job))
    {
      jobs_.push_back (job);
      suspended_jobs_.remove (job);
    }
  }

  void
  Scheduler::killall_jobs ()
  {
    ECHO ("killing all jobs!");

    // This implementation is quite inefficient because it will call
    // kill_job() for each job. But who cares? We are killing everyone
    // anyway.

    while (!jobs_to_start_.empty ())
      jobs_to_start_.pop_front ();

    while (!suspended_jobs_.empty ())
      kill_job (suspended_jobs_.front ());

    while (!if_change_jobs_.empty ())
      kill_job (if_change_jobs_.front ());

    while (!jobs_.empty ())
      kill_job (jobs_.front ());

    while (!deferred_jobs_.empty ())
      kill_job (deferred_jobs_.top ().get<1>());
  }

  void
  Scheduler::unschedule_job (Job* job)
  {
    assert (job);
    assert (job != current_job_);

    ECHO ("unscheduling job " << *job);

    // First of all, tell the job it has been terminated unless it has
    // been registered with us but not yet started.
    if (!libport::has (jobs_to_start_, job))
      job->terminate_now ();

    // Remove the job from the queues where it could be stored.
    jobs_to_start_.remove (job);
    jobs_.remove (job);
    suspended_jobs_.remove (job);
    if_change_jobs_.remove (job);

    // Remove it from live queues as well if the job is destroyed.
    to_start_.remove (job);
    pending_.remove (job);

    // We have no remove() on a priority queue, regenerate a queue without
    // this job.
    {
      deferred_jobs old_deferred;
      std::swap (old_deferred, deferred_jobs_);
      while (!old_deferred.empty ())
      {
	deferred_job j = old_deferred.top ();
	old_deferred.pop ();
	if (j.get<1>() != job)
	  deferred_jobs_.push (j);
      }
    }
  }

  void
  Scheduler::kill_job (Job* job)
  {
    assert (job != current_job_);

    ECHO ("deleting job " << *job);
    delete job;
  }

  bool operator> (const deferred_job& left, const deferred_job& right)
  {
    return left.get<0>() > right.get<0>();
  }

} // namespace scheduler
<commit_msg>Print an error if a job attempts to unschedule itself<commit_after>/**
 ** \file scheduler/scheduler.cc
 ** \brief Implementation of scheduler::Scheduler.
 */

//#define ENABLE_DEBUG_TRACES

#include <cassert>

#include <libport/compiler.hh>
#include <libport/containers.hh>
#include <libport/foreach.hh>

#include "kernel/userver.hh"

#include "object/urbi-exception.hh"

#include "scheduler/scheduler.hh"
#include "scheduler/job.hh"

namespace scheduler
{

  // This function is required to start a new job using the libcoroutine.
  // Its only purpose is to create the context and start the execution
  // of the new job.
  static void
  run_job (void* job)
  {
    static_cast<Job*>(job)->run();
  }

  void
  Scheduler::add_job (Job* job)
  {
    assert (job);
    assert (!libport::has (jobs_, job));
    assert (!libport::has (jobs_to_start_, job));
    jobs_to_start_.push_back (job);
  }

  libport::utime_t
  Scheduler::work ()
  {
#ifdef ENABLE_DEBUG_TRACES
    static int cycle = 0;
#endif
    ECHO ("======================================================== cycle "
	  << ++cycle);

    // Start new jobs
    to_start_.clear ();
    std::swap (to_start_, jobs_to_start_);
    foreach (Job* job, to_start_)
    {
      assert (job);
      ECHO ("will start job " << *job);
      // Job will start for a very short time and do a yield_front() to
      // be restarted below in the course of the regular cycle.
      assert (!current_job_);
      current_job_ = job;
      Coro_startCoro_ (self_, job->coro_get(), job, run_job);
      // We have to assume that a new job may have had side-effects.
      possible_side_effect_ = true;
    }

    // Start deferred jobs
    for (libport::utime_t current_time = ::urbiserver->getTime ();
	 !deferred_jobs_.empty();
	 deferred_jobs_.pop ())
    {
      deferred_job j = deferred_jobs_.top ();
      if (current_time < j.get<0>())
	break;
      jobs_.push_back (j.get<1> ());
    }

    // If something is going to happen, or if we have just started a
    // new job, add the list of jobs waiting for something to happen
    // on the pending jobs queue.
    if (!if_change_jobs_.empty() && (possible_side_effect_ || !jobs_.empty()))
    {
      foreach (Job* job, if_change_jobs_)
	jobs_.push_back (job);
      if_change_jobs_.clear ();
    }

    // Run all the jobs in the run queue once. If any job declares upon entry or
    // return that it is not side-effect free, we remember that for the next
    // cycle.
    possible_side_effect_ = false;
    pending_.clear ();
    std::swap (pending_, jobs_);

    ECHO (pending_.size() << " jobs in the queue for this cycle");
    foreach (Job* job, pending_)
    {
      assert (job);
      assert (!job->terminated ());
      ECHO ("will resume job " << *job);
      possible_side_effect_ |= !job->side_effect_free_get ();
      Coro_switchTo_ (self_, job->coro_get ());
      possible_side_effect_ |= !job->side_effect_free_get ();
      ECHO ("back from job " << *job);
    }

    // Do we have some work to do now?
    if (!jobs_.empty () || !jobs_to_start_.empty())
    {
      ECHO ("scheduler: asking to be recalled ASAP, " << jobs_.size() << " jobs ready and " << jobs_to_start_.size()
	    << " to start");
      return 0;
    }

    // Do we have deferred jobs?
    if (!deferred_jobs_.empty ())
    {
      ECHO ("scheduler: asking to be recalled later");
      return deferred_jobs_.top ().get<0> ();
    }

    // Ok, let's say, we'll be called again in one hour.
    ECHO ("scheduler: asking to be recalled in a long time");
    return ::urbiserver->getTime() + 3600000000LL;
  }

  void
  Scheduler::switch_back (Job* job)
  {
    // Switch back to the scheduler.
    assert (current_job_ == job);
    current_job_ = 0;
    Coro_switchTo_ (job->coro_get (), self_);
    // We regained control, we are again in the context of the job.
    assert (!current_job_);
    current_job_ = job;
    ECHO ("job " << *job << " resumed");
    // Check that we are not near exhausting the stack space.
    if (Coro_stackSpaceAlmostGone (job->coro_get ()))
      throw object::StackExhaustedError ("stack space exhausted");
    // Execute a deferred exception if any
    job->check_for_pending_exception ();
  }

  void
  Scheduler::resume_scheduler (Job* job)
  {
    // If the job has not terminated, put it at the back of the run queue
    // so that the run queue order is preserved between work cycles.
    if (!job->terminated ())
      jobs_.push_back (job);
    ECHO (*job << " has " << (job->terminated () ? "" : "not ") << "terminated");
    switch_back (job);
  }

  void
  Scheduler::resume_scheduler_front (Job* job)
  {
    // Put the job in front of the queue. If the job asks to be requeued,
    // it is not terminated.
    assert (!job->terminated ());
    jobs_.push_front (job);
    switch_back (job);
  }

  void
  Scheduler::resume_scheduler_until (Job* job, libport::utime_t deadline)
  {
    // Put the job in the deferred queue. If the job asks to be requeued,
    // it is not terminated.
    assert (!job->terminated ());
    deferred_jobs_.push (boost::make_tuple (deadline, job));
    switch_back (job);
  }

  void
  Scheduler::resume_scheduler_suspend (Job* job)
  {
    suspended_jobs_.push_back (job);
    switch_back (job);
  }

  void
  Scheduler::resume_scheduler_things_changed (Job* job)
  {
    if_change_jobs_.push_back (job);
    switch_back (job);
  }

  void
  Scheduler::resume_job (Job* job)
  {
    // Suspended job may have been killed externally, in which case it
    // will not appear in the list of suspended jobs.

    if (libport::has (suspended_jobs_, job))
    {
      jobs_.push_back (job);
      suspended_jobs_.remove (job);
    }
  }

  void
  Scheduler::killall_jobs ()
  {
    ECHO ("killing all jobs!");

    // This implementation is quite inefficient because it will call
    // kill_job() for each job. But who cares? We are killing everyone
    // anyway.

    while (!jobs_to_start_.empty ())
      jobs_to_start_.pop_front ();

    while (!suspended_jobs_.empty ())
      kill_job (suspended_jobs_.front ());

    while (!if_change_jobs_.empty ())
      kill_job (if_change_jobs_.front ());

    while (!jobs_.empty ())
      kill_job (jobs_.front ());

    while (!deferred_jobs_.empty ())
      kill_job (deferred_jobs_.top ().get<1>());
  }

  void
  Scheduler::unschedule_job (Job* job)
  {
    assert (job);
    if (job == current_job_)
    {
      std::cerr << *job << " asked to unschedule itself\n";
    }
    assert (job != current_job_);

    ECHO ("unscheduling job " << *job);

    // First of all, tell the job it has been terminated unless it has
    // been registered with us but not yet started.
    if (!libport::has (jobs_to_start_, job))
      job->terminate_now ();

    // Remove the job from the queues where it could be stored.
    jobs_to_start_.remove (job);
    jobs_.remove (job);
    suspended_jobs_.remove (job);
    if_change_jobs_.remove (job);

    // Remove it from live queues as well if the job is destroyed.
    to_start_.remove (job);
    pending_.remove (job);

    // We have no remove() on a priority queue, regenerate a queue without
    // this job.
    {
      deferred_jobs old_deferred;
      std::swap (old_deferred, deferred_jobs_);
      while (!old_deferred.empty ())
      {
	deferred_job j = old_deferred.top ();
	old_deferred.pop ();
	if (j.get<1>() != job)
	  deferred_jobs_.push (j);
      }
    }
  }

  void
  Scheduler::kill_job (Job* job)
  {
    assert (job != current_job_);

    ECHO ("deleting job " << *job);
    delete job;
  }

  bool operator> (const deferred_job& left, const deferred_job& right)
  {
    return left.get<0>() > right.get<0>();
  }

} // namespace scheduler
<|endoftext|>


<commit_before>//
// base.hpp
// ~~~~~~~~
//
// Copyright (c) 2014 Rick Yang (rick68 at gmail dot com)
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
//

#ifndef EIGENJS_BASIC_HPP
#define EIGENJS_BASIC_HPP

#include <v8.h>
#include <node.h>
#include <nan.h>

#include <boost/mpl/and.hpp>
#include <boost/mpl/or.hpp>

#include <eigen3/Eigen/Dense>

#include <complex>
#include <memory>
#include <type_traits>

#include "Complex_fwd.hpp"
#include "Matrix_fwd.hpp"
#include "CMatrix_fwd.hpp"
#include "Vector_fwd.hpp"
#include "CVector_fwd.hpp"
#include "RowVector_fwd.hpp"
#include "CRowVector_fwd.hpp"
#include "MatrixBlock_fwd.hpp"
#include "CMatrixBlock_fwd.hpp"
#include "VectorBlock_fwd.hpp"
#include "CVectorBlock_fwd.hpp"
#include "RowVectorBlock_fwd.hpp"
#include "CRowVectorBlock_fwd.hpp"

#include "detail/unwrap_eigen_block.hpp"
#include "detail/is_eigen_block.hpp"
#include "detail/is_eigen_matrix.hpp"

namespace EigenJS {

namespace detail {
  template <typename ScalarType>
  struct std_complex_dummy_ptr {
    typedef ScalarType scalar_type;
    typedef std::complex<scalar_type> value_type;

    NAN_INLINE value_type& operator*() { return value_; }
    NAN_INLINE const value_type& operator*() const { return value_; }
    NAN_INLINE value_type* operator->() { return &value_; }
    NAN_INLINE const value_type* operator->() const { return &value_; }

   private:
    value_type value_;
  };

}  // namespace detail

template <
  template <typename, typename, const char*> class Derived
, typename ScalarType
, typename ValueType
, const char* ClassName
>
struct base : node::ObjectWrap {
  typedef Derived<ScalarType, ValueType, ClassName> derived_type;

  typedef ScalarType scalar_type;
  typedef typename detail::unwrap_eigen_block<ValueType>::type value_type;

  typedef typename std::conditional<
      std::is_same<
        value_type
      , typename detail::std_complex_dummy_ptr<scalar_type>::value_type
      >::value
    , detail::std_complex_dummy_ptr<scalar_type>
    , std::shared_ptr<value_type>
    >::type pointer_type;

  static NAN_INLINE bool is_scalar(const v8::Handle<v8::Value>& arg) {
    return arg->IsNumber() ? true : false;
  }

  static NAN_INLINE bool is_complex(const v8::Handle<v8::Value>& arg) {
    return Complex<scalar_type>::base_type::has_instance(arg);
  }

  static NAN_INLINE bool
  is_complex_or_saclar(const v8::Handle<v8::Value>& arg) {
    return
      Complex<scalar_type>::base_type::has_instance(arg) || arg->IsNumber()
      ? true : false;
  }

  static NAN_INLINE bool is_matrix(const v8::Handle<v8::Value>& arg) {
    return Matrix<scalar_type>::base_type::has_instance(arg);
  }

  static NAN_INLINE bool is_cmatrix(const v8::Handle<v8::Value>& arg) {
    return CMatrix<scalar_type>::base_type::has_instance(arg);
  }

  static NAN_INLINE bool is_vector(const v8::Handle<v8::Value>& arg) {
    return Vector<scalar_type>::base_type::has_instance(arg);
  }

  static NAN_INLINE bool is_cvector(const v8::Handle<v8::Value>& arg) {
    return CVector<scalar_type>::base_type::has_instance(arg);
  }

  static NAN_INLINE bool is_rowvector(const v8::Handle<v8::Value>& arg) {
    return RowVector<scalar_type>::base_type::has_instance(arg);
  }

  static NAN_INLINE bool is_crowvector(const v8::Handle<v8::Value>& arg) {
    return CRowVector<scalar_type>::base_type::has_instance(arg);
  }

  static NAN_INLINE bool is_matrixblock(const v8::Handle<v8::Value>& arg) {
    return MatrixBlock<scalar_type>::base_type::has_instance(arg);
  }

  static NAN_INLINE bool is_cmatrixblock(const v8::Handle<v8::Value>& arg) {
    return CMatrixBlock<scalar_type>::base_type::has_instance(arg);
  }

  static NAN_INLINE bool is_vectorblock(const v8::Handle<v8::Value>& arg) {
    return VectorBlock<scalar_type>::base_type::has_instance(arg);
  }

  static NAN_INLINE bool is_cvectorblock(const v8::Handle<v8::Value>& arg) {
    return CVectorBlock<scalar_type>::base_type::has_instance(arg);
  }

  static NAN_INLINE bool is_rowvectorblock(const v8::Handle<v8::Value>& arg) {
    return RowVectorBlock<scalar_type>::base_type::has_instance(arg);
  }

  static NAN_INLINE bool is_crowvectorblock(const v8::Handle<v8::Value>& arg) {
    return CRowVectorBlock<scalar_type>::base_type::has_instance(arg);
  }

  static NAN_INLINE bool has_instance(const v8::Handle<v8::Value>& value) {
    NanScope();
    v8::Local<v8::FunctionTemplate> tpl = NanNew(function_template);
    return tpl->HasInstance(value);
  }

  template <typename T>
  static NAN_INLINE v8::Local<v8::Object>
  new_instance(const T& args, int argc, v8::Handle<v8::Value> argv[]) {
    v8::Local<v8::Function> ctor = NanNew(constructor);
    v8::Local<v8::Object> instance = ctor->NewInstance(argc, argv);
    return instance;
  }

  template <typename T, int Rows, int Cols>
  static NAN_INLINE bool is_out_of_range(
      const Eigen::Matrix<T, Rows, Cols>& eigen_matrix
    , const typename Eigen::Matrix<T, Rows, Cols>::Index& row
    , const typename Eigen::Matrix<T, Rows, Cols>::Index& col) {
    return row < 0 || row >= eigen_matrix.rows() ||
           col < 0 || col >= eigen_matrix.cols()
      ? NanThrowError("Row or column numbers are out of range"), true
      : false;
  }

  template <
    typename XprType
  , int BlockRows
  , int BlockCols
  , bool InnerPanel
  >
  static NAN_INLINE bool is_out_of_range(
      const Eigen::Block<
        XprType
      , BlockRows
      , BlockCols
      , InnerPanel
      >& eigen_block
    , const typename XprType::Index& row
    , const typename XprType::Index& col) {
    return row < 0 || row >= eigen_block.rows() ||
           col < 0 || col >= eigen_block.cols()
      ? NanThrowError("Row or column numbers are out of range"), true
      : false;
  }

  template <typename T, typename U>
  static NAN_INLINE
  typename std::enable_if<
    boost::mpl::and_<
      boost::mpl::or_<
        detail::is_eigen_block<typename T::value_type>
      , detail::is_eigen_matrix<typename T::value_type>
      >
    , boost::mpl::or_<
        detail::is_eigen_block<typename U::value_type>
      , detail::is_eigen_matrix<typename U::value_type>
      >
    >::value
  , bool
  >::type
  is_nonconformate_arguments(
      const T* const& op1
    , const U* const& op2) {
    return (*op1)->rows() != (*op2)->rows() ||
           (*op1)->cols() != (*op2)->cols()
      ? NanThrowError("Nonconformant arguments"), true
      : false;
  }

  template <typename T, typename U>
  static NAN_INLINE
  typename std::enable_if<
    boost::mpl::and_<
      boost::mpl::or_<
        detail::is_eigen_block<typename T::value_type>
      , detail::is_eigen_matrix<typename T::value_type>
      >
    , boost::mpl::or_<
        detail::is_eigen_block<typename U::value_type>
      , detail::is_eigen_matrix<typename U::value_type>
      >
    >::value
  , bool
  >::type
  is_invalid_matrix_product(
      const T* const& op1
    , const U* const& op2) {
    return (*op1)->cols() != (*op2)->rows()
      ? NanThrowError("Invalid matrix product"), true
      : false;
  }

  template <typename T>
  static NAN_INLINE
  typename std::enable_if<
    boost::mpl::or_<
      detail::is_eigen_block<typename T::value_type>
    , detail::is_eigen_matrix<typename T::value_type>
    >::value
  , bool
  >::type
  is_square_matrix(const T* const& op1) {
    return (*op1)->cols() == (*op1)->rows()
      ? true
      : (NanThrowError("The matrix must be square"), false);
  }

 public:
  NAN_INLINE value_type& operator*() { return *value_ptr_; }
  NAN_INLINE const value_type& operator*() const { return *value_ptr_; }
  NAN_INLINE value_type* operator->() { return value_ptr_.get(); }
  NAN_INLINE const value_type* operator->() const { return value_ptr_.get(); }

  NAN_INLINE operator const pointer_type&() const {
    return value_ptr_;
  }

 protected:
  base() : value_ptr_(new value_type()) {}

  explicit base(const Complex<scalar_type>&) : value_ptr_() {}

  explicit base(const pointer_type& value_ptr)
    : value_ptr_(value_ptr)
  {}

  ~base() {}

  static v8::Persistent<v8::FunctionTemplate> function_template;
  static v8::Persistent<v8::Function> constructor;

 private:
  friend derived_type;
  pointer_type value_ptr_;
};

template<
  template <typename, typename, const char*> class Derived
, typename ScalarType
, typename ValueType
, const char* ClassName
>
v8::Persistent<v8::FunctionTemplate>
    base<Derived, ScalarType, ValueType, ClassName>::function_template;

template<
  template <typename, typename, const char*> class Derived
, typename ScalarType
, typename ValueType
, const char* ClassName
>
v8::Persistent<v8::Function>
    base<Derived, ScalarType, ValueType, ClassName>::constructor;

}  // namespace EigenJS

#endif  // EIGENJS_BASIC_HPP
<commit_msg>src: fix a mistake about English sentence.<commit_after>//
// base.hpp
// ~~~~~~~~
//
// Copyright (c) 2014 Rick Yang (rick68 at gmail dot com)
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
//

#ifndef EIGENJS_BASIC_HPP
#define EIGENJS_BASIC_HPP

#include <v8.h>
#include <node.h>
#include <nan.h>

#include <boost/mpl/and.hpp>
#include <boost/mpl/or.hpp>

#include <eigen3/Eigen/Dense>

#include <complex>
#include <memory>
#include <type_traits>

#include "Complex_fwd.hpp"
#include "Matrix_fwd.hpp"
#include "CMatrix_fwd.hpp"
#include "Vector_fwd.hpp"
#include "CVector_fwd.hpp"
#include "RowVector_fwd.hpp"
#include "CRowVector_fwd.hpp"
#include "MatrixBlock_fwd.hpp"
#include "CMatrixBlock_fwd.hpp"
#include "VectorBlock_fwd.hpp"
#include "CVectorBlock_fwd.hpp"
#include "RowVectorBlock_fwd.hpp"
#include "CRowVectorBlock_fwd.hpp"

#include "detail/unwrap_eigen_block.hpp"
#include "detail/is_eigen_block.hpp"
#include "detail/is_eigen_matrix.hpp"

namespace EigenJS {

namespace detail {
  template <typename ScalarType>
  struct std_complex_dummy_ptr {
    typedef ScalarType scalar_type;
    typedef std::complex<scalar_type> value_type;

    NAN_INLINE value_type& operator*() { return value_; }
    NAN_INLINE const value_type& operator*() const { return value_; }
    NAN_INLINE value_type* operator->() { return &value_; }
    NAN_INLINE const value_type* operator->() const { return &value_; }

   private:
    value_type value_;
  };

}  // namespace detail

template <
  template <typename, typename, const char*> class Derived
, typename ScalarType
, typename ValueType
, const char* ClassName
>
struct base : node::ObjectWrap {
  typedef Derived<ScalarType, ValueType, ClassName> derived_type;

  typedef ScalarType scalar_type;
  typedef typename detail::unwrap_eigen_block<ValueType>::type value_type;

  typedef typename std::conditional<
      std::is_same<
        value_type
      , typename detail::std_complex_dummy_ptr<scalar_type>::value_type
      >::value
    , detail::std_complex_dummy_ptr<scalar_type>
    , std::shared_ptr<value_type>
    >::type pointer_type;

  static NAN_INLINE bool is_scalar(const v8::Handle<v8::Value>& arg) {
    return arg->IsNumber() ? true : false;
  }

  static NAN_INLINE bool is_complex(const v8::Handle<v8::Value>& arg) {
    return Complex<scalar_type>::base_type::has_instance(arg);
  }

  static NAN_INLINE bool
  is_complex_or_saclar(const v8::Handle<v8::Value>& arg) {
    return
      Complex<scalar_type>::base_type::has_instance(arg) || arg->IsNumber()
      ? true : false;
  }

  static NAN_INLINE bool is_matrix(const v8::Handle<v8::Value>& arg) {
    return Matrix<scalar_type>::base_type::has_instance(arg);
  }

  static NAN_INLINE bool is_cmatrix(const v8::Handle<v8::Value>& arg) {
    return CMatrix<scalar_type>::base_type::has_instance(arg);
  }

  static NAN_INLINE bool is_vector(const v8::Handle<v8::Value>& arg) {
    return Vector<scalar_type>::base_type::has_instance(arg);
  }

  static NAN_INLINE bool is_cvector(const v8::Handle<v8::Value>& arg) {
    return CVector<scalar_type>::base_type::has_instance(arg);
  }

  static NAN_INLINE bool is_rowvector(const v8::Handle<v8::Value>& arg) {
    return RowVector<scalar_type>::base_type::has_instance(arg);
  }

  static NAN_INLINE bool is_crowvector(const v8::Handle<v8::Value>& arg) {
    return CRowVector<scalar_type>::base_type::has_instance(arg);
  }

  static NAN_INLINE bool is_matrixblock(const v8::Handle<v8::Value>& arg) {
    return MatrixBlock<scalar_type>::base_type::has_instance(arg);
  }

  static NAN_INLINE bool is_cmatrixblock(const v8::Handle<v8::Value>& arg) {
    return CMatrixBlock<scalar_type>::base_type::has_instance(arg);
  }

  static NAN_INLINE bool is_vectorblock(const v8::Handle<v8::Value>& arg) {
    return VectorBlock<scalar_type>::base_type::has_instance(arg);
  }

  static NAN_INLINE bool is_cvectorblock(const v8::Handle<v8::Value>& arg) {
    return CVectorBlock<scalar_type>::base_type::has_instance(arg);
  }

  static NAN_INLINE bool is_rowvectorblock(const v8::Handle<v8::Value>& arg) {
    return RowVectorBlock<scalar_type>::base_type::has_instance(arg);
  }

  static NAN_INLINE bool is_crowvectorblock(const v8::Handle<v8::Value>& arg) {
    return CRowVectorBlock<scalar_type>::base_type::has_instance(arg);
  }

  static NAN_INLINE bool has_instance(const v8::Handle<v8::Value>& value) {
    NanScope();
    v8::Local<v8::FunctionTemplate> tpl = NanNew(function_template);
    return tpl->HasInstance(value);
  }

  template <typename T>
  static NAN_INLINE v8::Local<v8::Object>
  new_instance(const T& args, int argc, v8::Handle<v8::Value> argv[]) {
    v8::Local<v8::Function> ctor = NanNew(constructor);
    v8::Local<v8::Object> instance = ctor->NewInstance(argc, argv);
    return instance;
  }

  template <typename T, int Rows, int Cols>
  static NAN_INLINE bool is_out_of_range(
      const Eigen::Matrix<T, Rows, Cols>& eigen_matrix
    , const typename Eigen::Matrix<T, Rows, Cols>::Index& row
    , const typename Eigen::Matrix<T, Rows, Cols>::Index& col) {
    return row < 0 || row >= eigen_matrix.rows() ||
           col < 0 || col >= eigen_matrix.cols()
      ? NanThrowError("The row or column number is out of range"), true
      : false;
  }

  template <
    typename XprType
  , int BlockRows
  , int BlockCols
  , bool InnerPanel
  >
  static NAN_INLINE bool is_out_of_range(
      const Eigen::Block<
        XprType
      , BlockRows
      , BlockCols
      , InnerPanel
      >& eigen_block
    , const typename XprType::Index& row
    , const typename XprType::Index& col) {
    return row < 0 || row >= eigen_block.rows() ||
           col < 0 || col >= eigen_block.cols()
      ? NanThrowError("The row or column number is out of range"), true
      : false;
  }

  template <typename T, typename U>
  static NAN_INLINE
  typename std::enable_if<
    boost::mpl::and_<
      boost::mpl::or_<
        detail::is_eigen_block<typename T::value_type>
      , detail::is_eigen_matrix<typename T::value_type>
      >
    , boost::mpl::or_<
        detail::is_eigen_block<typename U::value_type>
      , detail::is_eigen_matrix<typename U::value_type>
      >
    >::value
  , bool
  >::type
  is_nonconformate_arguments(
      const T* const& op1
    , const U* const& op2) {
    return (*op1)->rows() != (*op2)->rows() ||
           (*op1)->cols() != (*op2)->cols()
      ? NanThrowError("Nonconformant arguments"), true
      : false;
  }

  template <typename T, typename U>
  static NAN_INLINE
  typename std::enable_if<
    boost::mpl::and_<
      boost::mpl::or_<
        detail::is_eigen_block<typename T::value_type>
      , detail::is_eigen_matrix<typename T::value_type>
      >
    , boost::mpl::or_<
        detail::is_eigen_block<typename U::value_type>
      , detail::is_eigen_matrix<typename U::value_type>
      >
    >::value
  , bool
  >::type
  is_invalid_matrix_product(
      const T* const& op1
    , const U* const& op2) {
    return (*op1)->cols() != (*op2)->rows()
      ? NanThrowError("Invalid matrix product"), true
      : false;
  }

  template <typename T>
  static NAN_INLINE
  typename std::enable_if<
    boost::mpl::or_<
      detail::is_eigen_block<typename T::value_type>
    , detail::is_eigen_matrix<typename T::value_type>
    >::value
  , bool
  >::type
  is_square_matrix(const T* const& op1) {
    return (*op1)->cols() == (*op1)->rows()
      ? true
      : (NanThrowError("The matrix must be square"), false);
  }

 public:
  NAN_INLINE value_type& operator*() { return *value_ptr_; }
  NAN_INLINE const value_type& operator*() const { return *value_ptr_; }
  NAN_INLINE value_type* operator->() { return value_ptr_.get(); }
  NAN_INLINE const value_type* operator->() const { return value_ptr_.get(); }

  NAN_INLINE operator const pointer_type&() const {
    return value_ptr_;
  }

 protected:
  base() : value_ptr_(new value_type()) {}

  explicit base(const Complex<scalar_type>&) : value_ptr_() {}

  explicit base(const pointer_type& value_ptr)
    : value_ptr_(value_ptr)
  {}

  ~base() {}

  static v8::Persistent<v8::FunctionTemplate> function_template;
  static v8::Persistent<v8::Function> constructor;

 private:
  friend derived_type;
  pointer_type value_ptr_;
};

template<
  template <typename, typename, const char*> class Derived
, typename ScalarType
, typename ValueType
, const char* ClassName
>
v8::Persistent<v8::FunctionTemplate>
    base<Derived, ScalarType, ValueType, ClassName>::function_template;

template<
  template <typename, typename, const char*> class Derived
, typename ScalarType
, typename ValueType
, const char* ClassName
>
v8::Persistent<v8::Function>
    base<Derived, ScalarType, ValueType, ClassName>::constructor;

}  // namespace EigenJS

#endif  // EIGENJS_BASIC_HPP
<|endoftext|>