<commit_before>// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#if defined(HAVE_CONFIG_H)
#include <config/bitcoin-config.h>
#endif

#include <fs.h>
#include <qt/intro.h>
#include <qt/forms/ui_intro.h>

#include <qt/guiconstants.h>
#include <qt/guiutil.h>

#include <interfaces/node.h>
#include <util/system.h>

#include <QFileDialog>
#include <QSettings>
#include <QMessageBox>

#include <cmath>

/* Total required space (in GB) depending on user choice (prune, not prune) */
static uint64_t requiredSpace;

/* Check free space asynchronously to prevent hanging the UI thread.

   Up to one request to check a path is in flight to this thread; when the check()
   function runs, the current path is requested from the associated Intro object.
   The reply is sent back through a signal.

   This ensures that no queue of checking requests is built up while the user is
   still entering the path, and that always the most recently entered path is checked as
   soon as the thread becomes available.
*/
class FreespaceChecker : public QObject
{
    Q_OBJECT

public:
    explicit FreespaceChecker(Intro *intro);

    enum Status {
        ST_OK,
        ST_ERROR
    };

public Q_SLOTS:
    void check();

Q_SIGNALS:
    void reply(int status, const QString &message, quint64 available);

private:
    Intro *intro;
};

#include <qt/intro.moc>

FreespaceChecker::FreespaceChecker(Intro *_intro)
{
    this->intro = _intro;
}

void FreespaceChecker::check()
{
    QString dataDirStr = intro->getPathToCheck();
    fs::path dataDir = GUIUtil::qstringToBoostPath(dataDirStr);
    uint64_t freeBytesAvailable = 0;
    int replyStatus = ST_OK;
    QString replyMessage = tr("A new data directory will be created.");

    /* Find first parent that exists, so that fs::space does not fail */
    fs::path parentDir = dataDir;
    fs::path parentDirOld = fs::path();
    while(parentDir.has_parent_path() && !fs::exists(parentDir))
    {
        parentDir = parentDir.parent_path();

        /* Check if we make any progress, break if not to prevent an infinite loop here */
        if (parentDirOld == parentDir)
            break;

        parentDirOld = parentDir;
    }

    try {
        freeBytesAvailable = fs::space(parentDir).available;
        if(fs::exists(dataDir))
        {
            if(fs::is_directory(dataDir))
            {
                QString separator = "" + QDir::toNativeSeparators("/") + tr("name") + "";
                replyStatus = ST_OK;
                replyMessage = tr("Directory already exists. Add %1 if you intend to create a new directory here.").arg(separator);
            } else {
                replyStatus = ST_ERROR;
                replyMessage = tr("Path already exists, and is not a directory.");
            }
        }
    } catch (const fs::filesystem_error&)
    {
        /* Parent directory does not exist or is not accessible */
        replyStatus = ST_ERROR;
        replyMessage = tr("Cannot create data directory here.");
    }
    Q_EMIT reply(replyStatus, replyMessage, freeBytesAvailable);
}

Intro::Intro(QWidget *parent, uint64_t blockchain_size, uint64_t chain_state_size) :
    QDialog(parent),
    ui(new Ui::Intro),
    thread(nullptr),
    signalled(false),
    m_blockchain_size(blockchain_size),
    m_chain_state_size(chain_state_size)
{
    ui->setupUi(this);
    ui->welcomeLabel->setText(ui->welcomeLabel->text().arg(tr(PACKAGE_NAME)));
    ui->storageLabel->setText(ui->storageLabel->text().arg(tr(PACKAGE_NAME)));

    ui->lblExplanation1->setText(ui->lblExplanation1->text()
        .arg(tr(PACKAGE_NAME))
        .arg(m_blockchain_size)
        .arg(2017)
        .arg(tr("Qtum"))
    );
    ui->lblExplanation2->setText(ui->lblExplanation2->text().arg(tr(PACKAGE_NAME)));

    uint64_t pruneTarget = std::max<int64_t>(0, gArgs.GetArg("-prune", 0));
    requiredSpace = m_blockchain_size;
    QString storageRequiresMsg = tr("At least %1 GB of data will be stored in this directory, and it will grow over time.");
    if (pruneTarget) {
        uint64_t prunedGBs = std::ceil(pruneTarget * 1024 * 1024.0 / GB_BYTES);
        if (prunedGBs <= requiredSpace) {
            requiredSpace = prunedGBs;
            storageRequiresMsg = tr("Approximately %1 GB of data will be stored in this directory.");
        }
        ui->lblExplanation3->setVisible(true);
    } else {
        ui->lblExplanation3->setVisible(false);
    }
    requiredSpace += m_chain_state_size;
    ui->sizeWarningLabel->setText(
        tr("%1 will download and store a copy of the Qtum block chain.").arg(tr(PACKAGE_NAME)) + " " +
        storageRequiresMsg.arg(requiredSpace) + " " +
        tr("The wallet will also be stored in this directory.")
    );
    startThread();
}

Intro::~Intro()
{
    delete ui;
    /* Ensure thread is finished before it is deleted */
    thread->quit();
    thread->wait();
}

QString Intro::getDataDirectory()
{
    return ui->dataDirectory->text();
}

void Intro::setDataDirectory(const QString &dataDir)
{
    ui->dataDirectory->setText(dataDir);
    if(dataDir == getDefaultDataDirectory())
    {
        ui->dataDirDefault->setChecked(true);
        ui->dataDirectory->setEnabled(false);
        ui->ellipsisButton->setEnabled(false);
    } else {
        ui->dataDirCustom->setChecked(true);
        ui->dataDirectory->setEnabled(true);
        ui->ellipsisButton->setEnabled(true);
    }
}

QString Intro::getDefaultDataDirectory()
{
    return GUIUtil::boostPathToQString(GetDefaultDataDir());
}

bool Intro::pickDataDirectory(interfaces::Node& node)
{
    QSettings settings;
    /* If data directory provided on command line, no need to look at settings
       or show a picking dialog */
    if(!gArgs.GetArg("-datadir", "").empty())
        return true;
    /* 1) Default data directory for operating system */
    QString dataDir = getDefaultDataDirectory();
    /* 2) Allow QSettings to override default dir */
    dataDir = settings.value("strDataDir", dataDir).toString();

    if(!fs::exists(GUIUtil::qstringToBoostPath(dataDir)) || gArgs.GetBoolArg("-choosedatadir", DEFAULT_CHOOSE_DATADIR) || settings.value("fReset", false).toBool() || gArgs.GetBoolArg("-resetguisettings", false))
    {
        /* Use selectParams here to guarantee Params() can be used by node interface */
        try {
            node.selectParams(gArgs.GetChainName());
        } catch (const std::exception&) {
            return false;
        }

        /* If current default data directory does not exist, let the user choose one */
        Intro intro(0, node.getAssumedBlockchainSize(), node.getAssumedChainStateSize());
        intro.setDataDirectory(dataDir);
        intro.setWindowIcon(QIcon(":icons/bitcoin"));

        while(true)
        {
            if(!intro.exec())
            {
                /* Cancel clicked */
                return false;
            }
            dataDir = intro.getDataDirectory();
            try {
                if (TryCreateDirectories(GUIUtil::qstringToBoostPath(dataDir))) {
                    // If a new data directory has been created, make wallets subdirectory too
                    TryCreateDirectories(GUIUtil::qstringToBoostPath(dataDir) / "wallets");
                }
                break;
            } catch (const fs::filesystem_error&) {
                QMessageBox::critical(nullptr, tr(PACKAGE_NAME),
                    tr("Error: Specified data directory \"%1\" cannot be created.").arg(dataDir));
                /* fall through, back to choosing screen */
            }
        }

        settings.setValue("strDataDir", dataDir);
        settings.setValue("fReset", false);
    }
    /* Only override -datadir if different from the default, to make it possible to
     * override -datadir in the bitcoin.conf file in the default data directory
     * (to be consistent with bitcoind behavior)
     */
    if(dataDir != getDefaultDataDirectory()) {
        node.softSetArg("-datadir", GUIUtil::qstringToBoostPath(dataDir).string()); // use OS locale for path setting
    }
    return true;
}

void Intro::setStatus(int status, const QString &message, quint64 bytesAvailable)
{
    switch(status)
    {
    case FreespaceChecker::ST_OK:
        ui->errorMessage->setText(message);
        ui->errorMessage->setStyleSheet("");
        break;
    case FreespaceChecker::ST_ERROR:
        ui->errorMessage->setText(tr("Error") + ": " + message);
        ui->errorMessage->setStyleSheet("QLabel { color: #800000 }");
        break;
    }
    /* Indicate number of bytes available */
    if(status == FreespaceChecker::ST_ERROR)
    {
        ui->freeSpace->setText("");
    } else {
        QString freeString = tr("%n GB of free space available", "", bytesAvailable/GB_BYTES);
        if(bytesAvailable < requiredSpace * GB_BYTES)
        {
            freeString += " " + tr("(of %n GB needed)", "", requiredSpace);
            ui->freeSpace->setStyleSheet("QLabel { color: #800000 }");
        } else {
            ui->freeSpace->setStyleSheet("");
        }
        ui->freeSpace->setText(freeString + ".");
    }
    /* Don't allow confirm in ERROR state */
    ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(status != FreespaceChecker::ST_ERROR);
}

void Intro::on_dataDirectory_textChanged(const QString &dataDirStr)
{
    /* Disable OK button until check result comes in */
    ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
    checkPath(dataDirStr);
}

void Intro::on_ellipsisButton_clicked()
{
    QString dir = QDir::toNativeSeparators(QFileDialog::getExistingDirectory(nullptr, "Choose data directory", ui->dataDirectory->text()));
    if(!dir.isEmpty())
        ui->dataDirectory->setText(dir);
}

void Intro::on_dataDirDefault_clicked()
{
    setDataDirectory(getDefaultDataDirectory());
}

void Intro::on_dataDirCustom_clicked()
{
    ui->dataDirectory->setEnabled(true);
    ui->ellipsisButton->setEnabled(true);
	#ifdef MAC_OSX
	setDataDirectory(QDir::homePath()+"/Qtum");
	#endif
}

void Intro::startThread()
{
    thread = new QThread(this);
    FreespaceChecker *executor = new FreespaceChecker(this);
    executor->moveToThread(thread);

    connect(executor, &FreespaceChecker::reply, this, &Intro::setStatus);
    connect(this, &Intro::requestCheck, executor, &FreespaceChecker::check);
    /*  make sure executor object is deleted in its own thread */
    connect(thread, &QThread::finished, executor, &QObject::deleteLater);

    thread->start();
}

void Intro::checkPath(const QString &dataDir)
{
    mutex.lock();
    pathToCheck = dataDir;
    if(!signalled)
    {
        signalled = true;
        Q_EMIT requestCheck();
    }
    mutex.unlock();
}

QString Intro::getPathToCheck()
{
    QString retval;
    mutex.lock();
    retval = pathToCheck;
    signalled = false; /* new request can be queued now */
    mutex.unlock();
    return retval;
}
<commit_msg>Fix indentation<commit_after>// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#if defined(HAVE_CONFIG_H)
#include <config/bitcoin-config.h>
#endif

#include <fs.h>
#include <qt/intro.h>
#include <qt/forms/ui_intro.h>

#include <qt/guiconstants.h>
#include <qt/guiutil.h>

#include <interfaces/node.h>
#include <util/system.h>

#include <QFileDialog>
#include <QSettings>
#include <QMessageBox>

#include <cmath>

/* Total required space (in GB) depending on user choice (prune, not prune) */
static uint64_t requiredSpace;

/* Check free space asynchronously to prevent hanging the UI thread.

   Up to one request to check a path is in flight to this thread; when the check()
   function runs, the current path is requested from the associated Intro object.
   The reply is sent back through a signal.

   This ensures that no queue of checking requests is built up while the user is
   still entering the path, and that always the most recently entered path is checked as
   soon as the thread becomes available.
*/
class FreespaceChecker : public QObject
{
    Q_OBJECT

public:
    explicit FreespaceChecker(Intro *intro);

    enum Status {
        ST_OK,
        ST_ERROR
    };

public Q_SLOTS:
    void check();

Q_SIGNALS:
    void reply(int status, const QString &message, quint64 available);

private:
    Intro *intro;
};

#include <qt/intro.moc>

FreespaceChecker::FreespaceChecker(Intro *_intro)
{
    this->intro = _intro;
}

void FreespaceChecker::check()
{
    QString dataDirStr = intro->getPathToCheck();
    fs::path dataDir = GUIUtil::qstringToBoostPath(dataDirStr);
    uint64_t freeBytesAvailable = 0;
    int replyStatus = ST_OK;
    QString replyMessage = tr("A new data directory will be created.");

    /* Find first parent that exists, so that fs::space does not fail */
    fs::path parentDir = dataDir;
    fs::path parentDirOld = fs::path();
    while(parentDir.has_parent_path() && !fs::exists(parentDir))
    {
        parentDir = parentDir.parent_path();

        /* Check if we make any progress, break if not to prevent an infinite loop here */
        if (parentDirOld == parentDir)
            break;

        parentDirOld = parentDir;
    }

    try {
        freeBytesAvailable = fs::space(parentDir).available;
        if(fs::exists(dataDir))
        {
            if(fs::is_directory(dataDir))
            {
                QString separator = "" + QDir::toNativeSeparators("/") + tr("name") + "";
                replyStatus = ST_OK;
                replyMessage = tr("Directory already exists. Add %1 if you intend to create a new directory here.").arg(separator);
            } else {
                replyStatus = ST_ERROR;
                replyMessage = tr("Path already exists, and is not a directory.");
            }
        }
    } catch (const fs::filesystem_error&)
    {
        /* Parent directory does not exist or is not accessible */
        replyStatus = ST_ERROR;
        replyMessage = tr("Cannot create data directory here.");
    }
    Q_EMIT reply(replyStatus, replyMessage, freeBytesAvailable);
}

Intro::Intro(QWidget *parent, uint64_t blockchain_size, uint64_t chain_state_size) :
    QDialog(parent),
    ui(new Ui::Intro),
    thread(nullptr),
    signalled(false),
    m_blockchain_size(blockchain_size),
    m_chain_state_size(chain_state_size)
{
    ui->setupUi(this);
    ui->welcomeLabel->setText(ui->welcomeLabel->text().arg(tr(PACKAGE_NAME)));
    ui->storageLabel->setText(ui->storageLabel->text().arg(tr(PACKAGE_NAME)));

    ui->lblExplanation1->setText(ui->lblExplanation1->text()
        .arg(tr(PACKAGE_NAME))
        .arg(m_blockchain_size)
        .arg(2017)
        .arg(tr("Qtum"))
    );
    ui->lblExplanation2->setText(ui->lblExplanation2->text().arg(tr(PACKAGE_NAME)));

    uint64_t pruneTarget = std::max<int64_t>(0, gArgs.GetArg("-prune", 0));
    requiredSpace = m_blockchain_size;
    QString storageRequiresMsg = tr("At least %1 GB of data will be stored in this directory, and it will grow over time.");
    if (pruneTarget) {
        uint64_t prunedGBs = std::ceil(pruneTarget * 1024 * 1024.0 / GB_BYTES);
        if (prunedGBs <= requiredSpace) {
            requiredSpace = prunedGBs;
            storageRequiresMsg = tr("Approximately %1 GB of data will be stored in this directory.");
        }
        ui->lblExplanation3->setVisible(true);
    } else {
        ui->lblExplanation3->setVisible(false);
    }
    requiredSpace += m_chain_state_size;
    ui->sizeWarningLabel->setText(
        tr("%1 will download and store a copy of the Qtum block chain.").arg(tr(PACKAGE_NAME)) + " " +
        storageRequiresMsg.arg(requiredSpace) + " " +
        tr("The wallet will also be stored in this directory.")
    );
    startThread();
}

Intro::~Intro()
{
    delete ui;
    /* Ensure thread is finished before it is deleted */
    thread->quit();
    thread->wait();
}

QString Intro::getDataDirectory()
{
    return ui->dataDirectory->text();
}

void Intro::setDataDirectory(const QString &dataDir)
{
    ui->dataDirectory->setText(dataDir);
    if(dataDir == getDefaultDataDirectory())
    {
        ui->dataDirDefault->setChecked(true);
        ui->dataDirectory->setEnabled(false);
        ui->ellipsisButton->setEnabled(false);
    } else {
        ui->dataDirCustom->setChecked(true);
        ui->dataDirectory->setEnabled(true);
        ui->ellipsisButton->setEnabled(true);
    }
}

QString Intro::getDefaultDataDirectory()
{
    return GUIUtil::boostPathToQString(GetDefaultDataDir());
}

bool Intro::pickDataDirectory(interfaces::Node& node)
{
    QSettings settings;
    /* If data directory provided on command line, no need to look at settings
       or show a picking dialog */
    if(!gArgs.GetArg("-datadir", "").empty())
        return true;
    /* 1) Default data directory for operating system */
    QString dataDir = getDefaultDataDirectory();
    /* 2) Allow QSettings to override default dir */
    dataDir = settings.value("strDataDir", dataDir).toString();

    if(!fs::exists(GUIUtil::qstringToBoostPath(dataDir)) || gArgs.GetBoolArg("-choosedatadir", DEFAULT_CHOOSE_DATADIR) || settings.value("fReset", false).toBool() || gArgs.GetBoolArg("-resetguisettings", false))
    {
        /* Use selectParams here to guarantee Params() can be used by node interface */
        try {
            node.selectParams(gArgs.GetChainName());
        } catch (const std::exception&) {
            return false;
        }

        /* If current default data directory does not exist, let the user choose one */
        Intro intro(0, node.getAssumedBlockchainSize(), node.getAssumedChainStateSize());
        intro.setDataDirectory(dataDir);
        intro.setWindowIcon(QIcon(":icons/bitcoin"));

        while(true)
        {
            if(!intro.exec())
            {
                /* Cancel clicked */
                return false;
            }
            dataDir = intro.getDataDirectory();
            try {
                if (TryCreateDirectories(GUIUtil::qstringToBoostPath(dataDir))) {
                    // If a new data directory has been created, make wallets subdirectory too
                    TryCreateDirectories(GUIUtil::qstringToBoostPath(dataDir) / "wallets");
                }
                break;
            } catch (const fs::filesystem_error&) {
                QMessageBox::critical(nullptr, tr(PACKAGE_NAME),
                    tr("Error: Specified data directory \"%1\" cannot be created.").arg(dataDir));
                /* fall through, back to choosing screen */
            }
        }

        settings.setValue("strDataDir", dataDir);
        settings.setValue("fReset", false);
    }
    /* Only override -datadir if different from the default, to make it possible to
     * override -datadir in the bitcoin.conf file in the default data directory
     * (to be consistent with bitcoind behavior)
     */
    if(dataDir != getDefaultDataDirectory()) {
        node.softSetArg("-datadir", GUIUtil::qstringToBoostPath(dataDir).string()); // use OS locale for path setting
    }
    return true;
}

void Intro::setStatus(int status, const QString &message, quint64 bytesAvailable)
{
    switch(status)
    {
    case FreespaceChecker::ST_OK:
        ui->errorMessage->setText(message);
        ui->errorMessage->setStyleSheet("");
        break;
    case FreespaceChecker::ST_ERROR:
        ui->errorMessage->setText(tr("Error") + ": " + message);
        ui->errorMessage->setStyleSheet("QLabel { color: #800000 }");
        break;
    }
    /* Indicate number of bytes available */
    if(status == FreespaceChecker::ST_ERROR)
    {
        ui->freeSpace->setText("");
    } else {
        QString freeString = tr("%n GB of free space available", "", bytesAvailable/GB_BYTES);
        if(bytesAvailable < requiredSpace * GB_BYTES)
        {
            freeString += " " + tr("(of %n GB needed)", "", requiredSpace);
            ui->freeSpace->setStyleSheet("QLabel { color: #800000 }");
        } else {
            ui->freeSpace->setStyleSheet("");
        }
        ui->freeSpace->setText(freeString + ".");
    }
    /* Don't allow confirm in ERROR state */
    ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(status != FreespaceChecker::ST_ERROR);
}

void Intro::on_dataDirectory_textChanged(const QString &dataDirStr)
{
    /* Disable OK button until check result comes in */
    ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
    checkPath(dataDirStr);
}

void Intro::on_ellipsisButton_clicked()
{
    QString dir = QDir::toNativeSeparators(QFileDialog::getExistingDirectory(nullptr, "Choose data directory", ui->dataDirectory->text()));
    if(!dir.isEmpty())
        ui->dataDirectory->setText(dir);
}

void Intro::on_dataDirDefault_clicked()
{
    setDataDirectory(getDefaultDataDirectory());
}

void Intro::on_dataDirCustom_clicked()
{
    ui->dataDirectory->setEnabled(true);
    ui->ellipsisButton->setEnabled(true);
    #ifdef MAC_OSX
    setDataDirectory(QDir::homePath()+"/Qtum");
    #endif
}

void Intro::startThread()
{
    thread = new QThread(this);
    FreespaceChecker *executor = new FreespaceChecker(this);
    executor->moveToThread(thread);

    connect(executor, &FreespaceChecker::reply, this, &Intro::setStatus);
    connect(this, &Intro::requestCheck, executor, &FreespaceChecker::check);
    /*  make sure executor object is deleted in its own thread */
    connect(thread, &QThread::finished, executor, &QObject::deleteLater);

    thread->start();
}

void Intro::checkPath(const QString &dataDir)
{
    mutex.lock();
    pathToCheck = dataDir;
    if(!signalled)
    {
        signalled = true;
        Q_EMIT requestCheck();
    }
    mutex.unlock();
}

QString Intro::getPathToCheck()
{
    QString retval;
    mutex.lock();
    retval = pathToCheck;
    signalled = false; /* new request can be queued now */
    mutex.unlock();
    return retval;
}
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2016      Los Alamos National Security, LLC
 *                         All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * LA-CC 10-123
 */

//@HEADER
// ***************************************************
//
// HPCG: High Performance Conjugate Gradient Benchmark
//
// Contact:
// Michael A. Heroux ( maherou@sandia.gov)
// Jack Dongarra     (dongarra@eecs.utk.edu)
// Piotr Luszczek    (luszczek@eecs.utk.edu)
//
// ***************************************************
//@HEADER

#include "hpcg.hpp"
#include "mytimer.hpp"
#include "Geometry.hpp"
#include "CheckAspectRatio.hpp"
#include "GenerateGeometry.hpp"

#include "LegionStuff.hpp"
#include "LegionArrays.hpp"
#include "LegionMatrices.hpp"
#include "CGMapper.h"

#include <iostream>
#include <cstdlib>
#include <deque>
#include <iomanip>

using namespace std;

LegionRuntime::Logger::Category Logger("LGNCG");

/**
 * SPMD Main Task //////////////////////////////////////////////////////////////
 */
void
spmdInitTask(
    const Task *task,
    const std::vector<PhysicalRegion> &regions,
    Context ctx, HighLevelRuntime *runtime
) {
    static const int ridParams = 0;
    static const int ridGeom   = 1;
    //
    const int nShards = *(int *)task->args;
    const int taskID = getTaskID(task);

    // XXX SKG LogicalRegion TEST
    PhysicalScalar<LogicalRegion> testPR(regions[2], ctx, runtime);
    LogicalRegion *TEST = testPR.data();
    assert(TEST);

    LogicalArray<double> foo;
    foo.allocate(1+taskID, ctx, runtime);
    auto pr = foo.mapRegion(ctx, runtime);

    (*TEST) = foo.logicalRegion;

    RegionAccessor<AccessorType::Generic, double> pracc =
    pr.get_field_accessor(foo.fid).typeify<double>();

    for (GenericPointInRectIterator<1> pir(foo.bounds); pir; pir++) {
        cout << "<--"<< (taskID + 1) << endl;
        pracc.write(DomainPoint::from_point<1>(pir.p), (double)(taskID + 1));
    }

    runtime->unmap_region(ctx, pr);

    cout << "SUCCESS!!!!" << endl;

    return;
    // END XXX SKG LogicalRegion TEST

    //
    PhysicalScalar<HPCG_Params> psHPCGParams(regions[ridParams], ctx, runtime);
    HPCG_Params *params = psHPCGParams.data();
    assert(params);
    //
    SPMDMeta spmdMeta = {.rank = taskID, .nRanks = nShards};
    HPCG_Init(*params, spmdMeta);
    // Check if QuickPath option is enabled.  If the running time is set to
    // zero, we minimize all paths through the program
    bool quickPath = (params->runningTime == 0);
    // Number of processes, my process ID
    int size = params->comm_size, rank = params->comm_rank;
    //
    local_int_t nx, ny,nz;
    nx = (local_int_t)params->nx;
    ny = (local_int_t)params->ny;
    nz = (local_int_t)params->nz;
    // Used to check return codes on function calls
    int ierr = 0;
    ierr = CheckAspectRatio(0.125, nx, ny, nz, "local problem", rank == 0);
    if (ierr) exit(ierr);
    ////////////////////////////////////////////////////////////////////////////
    // Problem setup Phase /////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////
    // Construct the geometry and linear system
    PhysicalScalar<Geometry> psGeometry(regions[ridGeom], ctx, runtime);
    Geometry *geom = psGeometry.data();
    assert(geom);
    GenerateGeometry(size, rank, params->numThreads, nx, ny, nz, geom);
    //
    ierr = CheckAspectRatio(0.125, geom->npx, geom->npy, geom->npz,
                            "process grid", rank == 0);
    if (ierr) exit(ierr);
    // Use this array for collecting timing information
    std::vector<double> times(10, 0.0);
    //
    double setup_time = mytimer();
}

/**
 *
 */
static void
generateInitGeometry(
    int nShards,
    Geometry &globalGeom
) {
    // We only care about passing nShards for this bit. rank doesn't make sense
    // in this context.
    const SPMDMeta meta = {.rank = 0, .nRanks = nShards};
    HPCG_Params params;
    HPCG_Init(params, meta);
    // Number of processes, my process ID
    const int size = params.comm_size, rank = params.comm_rank;
    //
    local_int_t nx, ny,nz;
    nx = (local_int_t)params.nx;
    ny = (local_int_t)params.ny;
    nz = (local_int_t)params.nz;
    // Generate geometry so we can get things like npx, npy, npz, etc.
    GenerateGeometry(size, rank, params.numThreads, nx, ny, nz, &globalGeom);
}

/**
 *
 */
static global_int_t
getGlobalXYZ(
    const Geometry &geom
) {
    return geom.npx * geom.nx *
           geom.npy * geom.ny *
           geom.npz * geom.nz;
}

/**
 *
 */
static void
createLogicalStructures(
    LogicalArray<HPCG_Params>   &hpcgParams,
    LogicalArray<Geometry>      &geometries,
    LogicalSparseMatrix<double> &A,
    LogicalArray<double>        &x,
    LogicalArray<double>        &y,
    const Geometry              &geom,
    Context ctx, HighLevelRuntime *runtime
) {
    cout << "*** Creating Logical Structures..." << endl;;
    const double initStart = mytimer();
    // Metadata - one for each SPMD task.
    hpcgParams.allocate(geom.size, ctx, runtime);
    hpcgParams.partition(geom.size, ctx, runtime);
    geometries.allocate(geom.size, ctx, runtime);
    geometries.partition(geom.size, ctx, runtime);
    // Application structures
    // First calculate global XYZ for the problem.
    global_int_t globalXYZ = getGlobalXYZ(geom);
    //A TODO
    x.allocate(globalXYZ, ctx, runtime);
    y.allocate(globalXYZ, ctx, runtime);
    const double initEnd = mytimer();
    const double initTime = initEnd - initStart;
    cout << "    Done in: " << initTime << " s" << endl;;
}

/**
 * Main Task ///////////////////////////////////////////////////////////////////
 * First task that gets spawned. Responsible for setup, etc.
 */
void
mainTask(
    const Task *,
    const std::vector<PhysicalRegion> &,
    Context ctx, HighLevelRuntime *runtime
) {
    // ask the mapper how many shards we can have
    const int nShards = runtime->get_tunable_value(
                            ctx, CGMapper::TID_NUM_SHARDS
                        );
    cout << "*** Number of Shards (~ NUMPE): " << nShards << endl;;
    ////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////
    // At this point we need to know some run parameters so we can allocate and
    // partition the logical data structures. We'll use this info to calculate
    // global values, etc. NOTE: not all members will contain valid data after
    // generateInitGeometry returns (e.g., rank, ipx, ipy, ipz).
    Geometry initGeom;
    generateInitGeometry(nShards, initGeom);
    cout << "*** Problem Information:"   << endl;
    cout << "    size=" << initGeom.size << endl;
    cout << "    npx="  << initGeom.npx  << endl;
    cout << "    npy="  << initGeom.npy  << endl;
    cout << "    npz="  << initGeom.npz  << endl;
    cout << "    nx="   << initGeom.nx   << endl;
    cout << "    ny="   << initGeom.ny   << endl;
    cout << "    nz="   << initGeom.nz   << endl;
    ////////////////////////////////////////////////////////////////////////////
    cout << "*** Starting Initialization..." << endl;;
    // Legion array holding HPCG parameters that impact run.
    LogicalArray<HPCG_Params> hpcgParams;
    // Legion array holding problem geometries.
    LogicalArray<Geometry> geometries;
    // Application structures.
    LogicalSparseMatrix<double> A;
    LogicalArray<double> x, y;
    //
    createLogicalStructures(
        hpcgParams,
        geometries,
        A,
        x,
        y,
        initGeom,
        ctx,
        runtime
    );
    // XXX SKG LogicalRegion TEST
    LogicalArray<LogicalRegion> testLR;
    testLR.allocate(initGeom.size, ctx, runtime);
    testLR.partition(initGeom.size, ctx, runtime);
    // END XXX SKG LogicalRegion TEST
    cout << "*** Launching Initialization Tasks..." << endl;;
    const double initStart = mytimer();
    IndexLauncher launcher(
        SPMD_INIT_TID,
        hpcgParams.launchDomain(),
        TaskArgument(&nShards, sizeof(nShards)),
        ArgumentMap()
    );
    //
    launcher.add_region_requirement(
        RegionRequirement(
            hpcgParams.logicalPartition(),
            0,
            WRITE_DISCARD,
            EXCLUSIVE,
            hpcgParams.logicalRegion
        )
    ).add_field(hpcgParams.fid);
    //
    launcher.add_region_requirement(
        RegionRequirement(
            geometries.logicalPartition(),
            0,
            WRITE_DISCARD,
            EXCLUSIVE,
            geometries.logicalRegion
        )
    ).add_field(geometries.fid);
    // XXX SKG LogicalRegion TEST
    launcher.add_region_requirement(
        RegionRequirement(
            testLR.logicalPartition(),
            0,
            WRITE_DISCARD,
            EXCLUSIVE,
            testLR.logicalRegion
        )
    ).add_field(testLR.fid);
    // END XXX SKG LogicalRegion TEST
    //
    auto futureMap = runtime->execute_index_space(ctx, launcher);
    cout << "*** Waiting for Initialization Tasks" << endl;
    futureMap.wait_all_results();
    const double initEnd = mytimer();
    const double initTime = initEnd - initStart;
    cout << "*** Initialization Time (s): " << initTime << endl;

    // XXX SKG LogicalRegion TEST
    auto prs = testLR.mapRegion(ctx, runtime);
    RegionAccessor<AccessorType::Generic, LogicalRegion> pracc =
        prs.get_field_accessor(testLR.fid).typeify<LogicalRegion>();

    for (GenericPointInRectIterator<1> pir(testLR.bounds); pir; pir++) {
        auto lr = pracc.read(DomainPoint::from_point<1>(pir.p));
        RegionRequirement req(
            lr, READ_ONLY, EXCLUSIVE, lr
        );
        req.add_field(0);
        InlineLauncher inl(req);
        PhysicalRegion reg = runtime->map_region(ctx, inl);
        reg.wait_until_valid();
        Domain tDom = runtime->get_index_space_domain(
            ctx, reg.get_logical_region().get_index_space()
        );
        RegionAccessor<AccessorType::Generic, double> blacc =
            reg.get_field_accessor(0).typeify<double>();
        for (GenericPointInRectIterator<1> piri(tDom.get_rect<1>()); piri; piri++) {
            auto blah = blacc.read(DomainPoint::from_point<1>(piri.p));
            cout << "-->" << blah;
        }
        runtime->unmap_region(ctx, reg);
        cout << endl;
    }
    // END XXX SKG LogicalRegion TEST
    //
    cout << "*** Cleaning Up..." << endl;
    hpcgParams.deallocate(ctx, runtime);
    geometries.deallocate(ctx, runtime);
    // A TODO
    x.deallocate(ctx, runtime);
    y.deallocate(ctx, runtime);
    // TODO RM
    testLR.deallocate(ctx, runtime);
}

/**
 * Main ////////////////////////////////////////////////////////////////////////
 * Responsible for RT initialization.
 */
int
main(int argc, char **argv)
{
    LegionInit();
    return Runtime::start(argc, argv);
}
<commit_msg>Add destroyLogicalStructures function.<commit_after>/**
 * Copyright (c) 2016      Los Alamos National Security, LLC
 *                         All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * LA-CC 10-123
 */

//@HEADER
// ***************************************************
//
// HPCG: High Performance Conjugate Gradient Benchmark
//
// Contact:
// Michael A. Heroux ( maherou@sandia.gov)
// Jack Dongarra     (dongarra@eecs.utk.edu)
// Piotr Luszczek    (luszczek@eecs.utk.edu)
//
// ***************************************************
//@HEADER

#include "hpcg.hpp"
#include "mytimer.hpp"
#include "Geometry.hpp"
#include "CheckAspectRatio.hpp"
#include "GenerateGeometry.hpp"

#include "LegionStuff.hpp"
#include "LegionArrays.hpp"
#include "LegionMatrices.hpp"
#include "CGMapper.h"

#include <iostream>
#include <cstdlib>
#include <deque>
#include <iomanip>

using namespace std;

LegionRuntime::Logger::Category Logger("LGNCG");

/**
 * SPMD Main Task //////////////////////////////////////////////////////////////
 */
void
spmdInitTask(
    const Task *task,
    const std::vector<PhysicalRegion> &regions,
    Context ctx, HighLevelRuntime *runtime
) {
    static const int ridParams = 0;
    static const int ridGeom   = 1;
    //
    const int nShards = *(int *)task->args;
    const int taskID = getTaskID(task);

    // XXX SKG LogicalRegion TEST
    PhysicalScalar<LogicalRegion> testPR(regions[2], ctx, runtime);
    LogicalRegion *TEST = testPR.data();
    assert(TEST);

    LogicalArray<double> foo;
    foo.allocate(1+taskID, ctx, runtime);
    auto pr = foo.mapRegion(ctx, runtime);

    (*TEST) = foo.logicalRegion;

    RegionAccessor<AccessorType::Generic, double> pracc =
    pr.get_field_accessor(foo.fid).typeify<double>();

    for (GenericPointInRectIterator<1> pir(foo.bounds); pir; pir++) {
        cout << "<--"<< (taskID + 1) << endl;
        pracc.write(DomainPoint::from_point<1>(pir.p), (double)(taskID + 1));
    }

    runtime->unmap_region(ctx, pr);

    cout << "SUCCESS!!!!" << endl;

    return;
    // END XXX SKG LogicalRegion TEST

    //
    PhysicalScalar<HPCG_Params> psHPCGParams(regions[ridParams], ctx, runtime);
    HPCG_Params *params = psHPCGParams.data();
    assert(params);
    //
    SPMDMeta spmdMeta = {.rank = taskID, .nRanks = nShards};
    HPCG_Init(*params, spmdMeta);
    // Check if QuickPath option is enabled.  If the running time is set to
    // zero, we minimize all paths through the program
    bool quickPath = (params->runningTime == 0);
    // Number of processes, my process ID
    int size = params->comm_size, rank = params->comm_rank;
    //
    local_int_t nx, ny,nz;
    nx = (local_int_t)params->nx;
    ny = (local_int_t)params->ny;
    nz = (local_int_t)params->nz;
    // Used to check return codes on function calls
    int ierr = 0;
    ierr = CheckAspectRatio(0.125, nx, ny, nz, "local problem", rank == 0);
    if (ierr) exit(ierr);
    ////////////////////////////////////////////////////////////////////////////
    // Problem setup Phase /////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////
    // Construct the geometry and linear system
    PhysicalScalar<Geometry> psGeometry(regions[ridGeom], ctx, runtime);
    Geometry *geom = psGeometry.data();
    assert(geom);
    GenerateGeometry(size, rank, params->numThreads, nx, ny, nz, geom);
    //
    ierr = CheckAspectRatio(0.125, geom->npx, geom->npy, geom->npz,
                            "process grid", rank == 0);
    if (ierr) exit(ierr);
    // Use this array for collecting timing information
    std::vector<double> times(10, 0.0);
    //
    double setup_time = mytimer();
}

/**
 *
 */
static void
generateInitGeometry(
    int nShards,
    Geometry &globalGeom
) {
    // We only care about passing nShards for this bit. rank doesn't make sense
    // in this context.
    const SPMDMeta meta = {.rank = 0, .nRanks = nShards};
    HPCG_Params params;
    HPCG_Init(params, meta);
    // Number of processes, my process ID
    const int size = params.comm_size, rank = params.comm_rank;
    //
    local_int_t nx, ny,nz;
    nx = (local_int_t)params.nx;
    ny = (local_int_t)params.ny;
    nz = (local_int_t)params.nz;
    // Generate geometry so we can get things like npx, npy, npz, etc.
    GenerateGeometry(size, rank, params.numThreads, nx, ny, nz, &globalGeom);
}

/**
 *
 */
static global_int_t
getGlobalXYZ(
    const Geometry &geom
) {
    return geom.npx * geom.nx *
           geom.npy * geom.ny *
           geom.npz * geom.nz;
}

/**
 *
 */
static void
createLogicalStructures(
    LogicalArray<HPCG_Params>   &hpcgParams,
    LogicalArray<Geometry>      &geometries,
    LogicalSparseMatrix<double> &A,
    LogicalArray<double>        &x,
    LogicalArray<double>        &y,
    const Geometry              &geom,
    Context ctx, HighLevelRuntime *runtime
) {
    cout << "*** Creating Logical Structures..." << endl;;
    const double initStart = mytimer();
    // Metadata - one for each SPMD task.
    hpcgParams.allocate(geom.size, ctx, runtime);
    hpcgParams.partition(geom.size, ctx, runtime);
    geometries.allocate(geom.size, ctx, runtime);
    geometries.partition(geom.size, ctx, runtime);
    // Application structures
    // First calculate global XYZ for the problem.
    global_int_t globalXYZ = getGlobalXYZ(geom);
    //A TODO
    x.allocate(globalXYZ, ctx, runtime);
    y.allocate(globalXYZ, ctx, runtime);
    const double initEnd = mytimer();
    const double initTime = initEnd - initStart;
    cout << "    Done in: " << initTime << " s" << endl;;
}

/**
 *
 */
static void
destroyLogicalStructures(
    LogicalArray<HPCG_Params>   &hpcgParams,
    LogicalArray<Geometry>      &geometries,
    LogicalSparseMatrix<double> &A,
    LogicalArray<double>        &x,
    LogicalArray<double>        &y,
    Context ctx, HighLevelRuntime *runtime
) {
    cout << "*** Destroying Logical Structures..." << endl;;
    const double initStart = mytimer();
    hpcgParams.deallocate(ctx, runtime);
    geometries.deallocate(ctx, runtime);
    // A TODO
    x.deallocate(ctx, runtime);
    y.deallocate(ctx, runtime);
    const double initEnd = mytimer();
    const double initTime = initEnd - initStart;
    cout << "    Done in: " << initTime << " s" << endl;;
}

/**
 * Main Task ///////////////////////////////////////////////////////////////////
 * First task that gets spawned. Responsible for setup, etc.
 */
void
mainTask(
    const Task *,
    const std::vector<PhysicalRegion> &,
    Context ctx, HighLevelRuntime *runtime
) {
    // ask the mapper how many shards we can have
    const int nShards = runtime->get_tunable_value(
                            ctx, CGMapper::TID_NUM_SHARDS
                        );
    cout << "*** Number of Shards (~ NUMPE): " << nShards << endl;;
    ////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////
    // At this point we need to know some run parameters so we can allocate and
    // partition the logical data structures. We'll use this info to calculate
    // global values, etc. NOTE: not all members will contain valid data after
    // generateInitGeometry returns (e.g., rank, ipx, ipy, ipz).
    Geometry initGeom;
    generateInitGeometry(nShards, initGeom);
    cout << "*** Problem Information:"   << endl;
    cout << "    size=" << initGeom.size << endl;
    cout << "    npx="  << initGeom.npx  << endl;
    cout << "    npy="  << initGeom.npy  << endl;
    cout << "    npz="  << initGeom.npz  << endl;
    cout << "    nx="   << initGeom.nx   << endl;
    cout << "    ny="   << initGeom.ny   << endl;
    cout << "    nz="   << initGeom.nz   << endl;
    ////////////////////////////////////////////////////////////////////////////
    cout << "*** Starting Initialization..." << endl;;
    // Legion array holding HPCG parameters that impact run.
    LogicalArray<HPCG_Params> hpcgParams;
    // Legion array holding problem geometries.
    LogicalArray<Geometry> geometries;
    // Application structures.
    LogicalSparseMatrix<double> A;
    LogicalArray<double> x, y;
    //
    createLogicalStructures(
        hpcgParams,
        geometries,
        A,
        x,
        y,
        initGeom,
        ctx,
        runtime
    );
    // XXX SKG LogicalRegion TEST
    LogicalArray<LogicalRegion> testLR;
    testLR.allocate(initGeom.size, ctx, runtime);
    testLR.partition(initGeom.size, ctx, runtime);
    // END XXX SKG LogicalRegion TEST
    cout << "*** Launching Initialization Tasks..." << endl;;
    const double initStart = mytimer();
    IndexLauncher launcher(
        SPMD_INIT_TID,
        hpcgParams.launchDomain(),
        TaskArgument(&nShards, sizeof(nShards)),
        ArgumentMap()
    );
    //
    launcher.add_region_requirement(
        RegionRequirement(
            hpcgParams.logicalPartition(),
            0,
            WRITE_DISCARD,
            EXCLUSIVE,
            hpcgParams.logicalRegion
        )
    ).add_field(hpcgParams.fid);
    //
    launcher.add_region_requirement(
        RegionRequirement(
            geometries.logicalPartition(),
            0,
            WRITE_DISCARD,
            EXCLUSIVE,
            geometries.logicalRegion
        )
    ).add_field(geometries.fid);
    // XXX SKG LogicalRegion TEST
    launcher.add_region_requirement(
        RegionRequirement(
            testLR.logicalPartition(),
            0,
            WRITE_DISCARD,
            EXCLUSIVE,
            testLR.logicalRegion
        )
    ).add_field(testLR.fid);
    // END XXX SKG LogicalRegion TEST
    //
    auto futureMap = runtime->execute_index_space(ctx, launcher);
    cout << "*** Waiting for Initialization Tasks" << endl;
    futureMap.wait_all_results();
    const double initEnd = mytimer();
    const double initTime = initEnd - initStart;
    cout << "*** Initialization Time (s): " << initTime << endl;

    // XXX SKG LogicalRegion TEST
    auto prs = testLR.mapRegion(ctx, runtime);
    RegionAccessor<AccessorType::Generic, LogicalRegion> pracc =
        prs.get_field_accessor(testLR.fid).typeify<LogicalRegion>();

    for (GenericPointInRectIterator<1> pir(testLR.bounds); pir; pir++) {
        auto lr = pracc.read(DomainPoint::from_point<1>(pir.p));
        RegionRequirement req(
            lr, READ_ONLY, EXCLUSIVE, lr
        );
        req.add_field(0);
        InlineLauncher inl(req);
        PhysicalRegion reg = runtime->map_region(ctx, inl);
        reg.wait_until_valid();
        Domain tDom = runtime->get_index_space_domain(
            ctx, reg.get_logical_region().get_index_space()
        );
        RegionAccessor<AccessorType::Generic, double> blacc =
            reg.get_field_accessor(0).typeify<double>();
        for (GenericPointInRectIterator<1> piri(tDom.get_rect<1>()); piri; piri++) {
            auto blah = blacc.read(DomainPoint::from_point<1>(piri.p));
            cout << "-->" << blah;
        }
        runtime->unmap_region(ctx, reg);
        cout << endl;
    }
    // END XXX SKG LogicalRegion TEST
    //
    cout << "*** Cleaning Up..." << endl;
    destroyLogicalStructures(
        hpcgParams,
        geometries,
        A,
        x,
        y,
        ctx,
        runtime
    );
    // XXX SKG LogicalRegion TEST
    testLR.deallocate(ctx, runtime);
    // END XXX SKG LogicalRegion TEST
}

/**
 * Main ////////////////////////////////////////////////////////////////////////
 * Responsible for RT initialization.
 */
int
main(int argc, char **argv)
{
    LegionInit();
    return Runtime::start(argc, argv);
}
<|endoftext|>


<commit_before>// Copyright 2004-present Facebook. All Rights Reserved.

#include <iomanip>
#include <map>
#include <string>
#include <sstream>
#include <vector>

#include <boost/lexical_cast.hpp>

#include "osquery/core.h"
#include "osquery/database.h"

#define FEATURE(name, reg, bit) std::make_pair(name, std::make_pair(reg, bit))

namespace osquery {
namespace tables {

typedef std::pair<std::string, int> RegisterBit_t;
typedef std::pair<std::string, RegisterBit_t> FeatureDef_t;

std::map<int, std::vector<FeatureDef_t> > kCPUFeatures = {
    {1,
     {
      FEATURE("pae", "edx", 6),
      FEATURE("msr", "edx", 5),
      FEATURE("mtrr", "edx", 12),
      FEATURE("acpi", "edx", 22),
      FEATURE("htt", "edx", 28),
      FEATURE("ia64", "edx", 30),
      FEATURE("vmx", "ecx", 5),
      FEATURE("smx", "ecx", 6),
      FEATURE("hypervisor", "ecx", 31),
      FEATURE("aes", "ecx", 25),
     }},
    {7,
     {
      FEATURE("mpx", "ebx", 14), FEATURE("sha", "ebx", 29),
     }},
};

void cpuid(unsigned int eax, unsigned int ecx, int regs[4]) {
  asm volatile("cpuid"
               : "=a"(regs[0]), "=b"(regs[1]), "=c"(regs[2]), "=d"(regs[3])
               : "a"(eax), "c"(ecx));
}

void registerToString(int reg, std::stringstream& stream) {
  for (size_t i = 0; i < 4; i++) {
    stream << ((char*)&reg)[i];
  }
}

bool isBitSet(size_t bit, unsigned int reg) {
  return ((reg & (1 << bit)) != 0);
}

Status genVendorString(QueryData& results) {
  int regs[4] = {-1};

  cpuid(0, 0, regs);
  if (regs[0] < 1) {
    // The CPUID ASM call is not supported.
    return Status(1, "Failed to run cpuid");
  }

  std::stringstream vendor_string;
  registerToString(regs[1], vendor_string);
  registerToString(regs[3], vendor_string);
  registerToString(regs[2], vendor_string);

  Row r;
  r["feature"] = "vendor";
  r["value"] = vendor_string.str();
  r["output_register"] = "ebx,edx,ecx";
  r["input_eax"] = "0";
  results.push_back(r);

  return Status(0, "OK");
}

void genFamily(QueryData& results) {
  int regs[4] = {-1};

  cpuid(1, 0, regs);
  int family = regs[0] & 0xf00;

  std::stringstream family_string;
  family_string << std::hex << std::setw(4) << std::setfill('0') << family;

  Row r;
  r["feature"] = "family";
  r["value"] = family_string.str();
  r["output_register"] = "eax";
  r["output_bit"] = "";
  r["input_eax"] = "1";

  results.push_back(r);
}

QueryData genCPUID() {
  QueryData results;

  if (!genVendorString(results).ok()) {
    return results;
  }

  // Get the CPU meta-data about the model, stepping, family.
  genFamily(results);

  int regs[4] = {-1};
  int feature_register, feature_bit;
  for (auto& feature_set : kCPUFeatures) {
    int eax = feature_set.first;
    cpuid(eax, 0, regs);

    for (auto& feature : feature_set.second) {
      Row r;

      r["feature"] = feature.first;

      // Get the return register holding the feature bit.
      feature_register = 0;
      if (feature.second.first == "edx") {
        feature_register = 3;
      } else if (feature.second.first == "ebx") {
        feature_register = 1;
      } else if (feature.second.first == "ecx") {
        feature_register = 2;
      }

      feature_bit = feature.second.second;
      r["value"] = isBitSet(feature_bit, regs[feature_register]) ? "1" : "0";
      r["output_register"] = feature.second.first;
      r["output_bit"] = boost::lexical_cast<std::string>(feature_bit);
      r["input_eax"] = boost::lexical_cast<std::string>(eax);
      results.push_back(r);
    }
  }

  return results;
}
}
}
<commit_msg>Set ouput_bit to 0 instead of cast error<commit_after>// Copyright 2004-present Facebook. All Rights Reserved.

#include <iomanip>
#include <map>
#include <string>
#include <sstream>
#include <vector>

#include <boost/lexical_cast.hpp>

#include "osquery/core.h"
#include "osquery/database.h"

#define FEATURE(name, reg, bit) std::make_pair(name, std::make_pair(reg, bit))

namespace osquery {
namespace tables {

typedef std::pair<std::string, int> RegisterBit_t;
typedef std::pair<std::string, RegisterBit_t> FeatureDef_t;

std::map<int, std::vector<FeatureDef_t> > kCPUFeatures = {
    {1,
     {
      FEATURE("pae", "edx", 6),
      FEATURE("msr", "edx", 5),
      FEATURE("mtrr", "edx", 12),
      FEATURE("acpi", "edx", 22),
      FEATURE("htt", "edx", 28),
      FEATURE("ia64", "edx", 30),
      FEATURE("vmx", "ecx", 5),
      FEATURE("smx", "ecx", 6),
      FEATURE("hypervisor", "ecx", 31),
      FEATURE("aes", "ecx", 25),
     }},
    {7,
     {
      FEATURE("mpx", "ebx", 14), FEATURE("sha", "ebx", 29),
     }},
};

void cpuid(unsigned int eax, unsigned int ecx, int regs[4]) {
  asm volatile("cpuid"
               : "=a"(regs[0]), "=b"(regs[1]), "=c"(regs[2]), "=d"(regs[3])
               : "a"(eax), "c"(ecx));
}

void registerToString(int reg, std::stringstream& stream) {
  for (size_t i = 0; i < 4; i++) {
    stream << ((char*)&reg)[i];
  }
}

bool isBitSet(size_t bit, unsigned int reg) {
  return ((reg & (1 << bit)) != 0);
}

Status genVendorString(QueryData& results) {
  int regs[4] = {-1};

  cpuid(0, 0, regs);
  if (regs[0] < 1) {
    // The CPUID ASM call is not supported.
    return Status(1, "Failed to run cpuid");
  }

  std::stringstream vendor_string;
  registerToString(regs[1], vendor_string);
  registerToString(regs[3], vendor_string);
  registerToString(regs[2], vendor_string);

  Row r;
  r["feature"] = "vendor";
  r["value"] = vendor_string.str();
  r["output_register"] = "ebx,edx,ecx";
  r["output_bit"] = "0";
  r["input_eax"] = "0";
  results.push_back(r);

  return Status(0, "OK");
}

void genFamily(QueryData& results) {
  int regs[4] = {-1};

  cpuid(1, 0, regs);
  int family = regs[0] & 0xf00;

  std::stringstream family_string;
  family_string << std::hex << std::setw(4) << std::setfill('0') << family;

  Row r;
  r["feature"] = "family";
  r["value"] = family_string.str();
  r["output_register"] = "eax";
  r["output_bit"] = "0";
  r["input_eax"] = "1";

  results.push_back(r);
}

QueryData genCPUID() {
  QueryData results;

  if (!genVendorString(results).ok()) {
    return results;
  }

  // Get the CPU meta-data about the model, stepping, family.
  genFamily(results);

  int regs[4] = {-1};
  int feature_register, feature_bit;
  for (auto& feature_set : kCPUFeatures) {
    int eax = feature_set.first;
    cpuid(eax, 0, regs);

    for (auto& feature : feature_set.second) {
      Row r;

      r["feature"] = feature.first;

      // Get the return register holding the feature bit.
      feature_register = 0;
      if (feature.second.first == "edx") {
        feature_register = 3;
      } else if (feature.second.first == "ebx") {
        feature_register = 1;
      } else if (feature.second.first == "ecx") {
        feature_register = 2;
      }

      feature_bit = feature.second.second;
      r["value"] = isBitSet(feature_bit, regs[feature_register]) ? "1" : "0";
      r["output_register"] = feature.second.first;
      r["output_bit"] = boost::lexical_cast<std::string>(feature_bit);
      r["input_eax"] = boost::lexical_cast<std::string>(eax);
      results.push_back(r);
    }
  }

  return results;
}
}
}
<|endoftext|>


<commit_before>
#pragma once

#include <reflectionzeug/variant/Variant.h>

#include <reflectionzeug/property/AccessorValue.h>

namespace
{

template <typename ValueType>
struct ConvertTo
{
    static ValueType convertTo(const reflectionzeug::Variant & variant) {
        return ValueType();
    }
};

template <>
struct ConvertTo<std::string>
{
    static std::string convertTo(const reflectionzeug::Variant & variant) {
        return variant.toJSON();
    }
};

} // namespace

namespace reflectionzeug
{

template <typename ValueType>
Variant Variant::fromValue(const ValueType & value)
{
    Variant variant;
    variant.m_accessor = new AccessorValue<ValueType>(value);
    return variant;
}

template <typename ValueType>
bool Variant::hasType() const
{
    if (!m_accessor) {
        return false;
    }

    return typeid(ValueType) == m_accessor->type();
}

template <typename ValueType>
bool Variant::canConvert() const
{
    if (!m_accessor) {
        return false;
    }

    return m_accessor->canConvert(typeid(ValueType)) || hasType<ValueType>();
}

template <typename ValueType>
ValueType Variant::value(const ValueType & defaultValue) const
{
    // Type of variant is the wanted type
    if (m_accessor && typeid(ValueType) == m_accessor->type()) {
        return static_cast<AccessorValue<ValueType> *>(m_accessor)->value();
    }

    // Variant has to be converted
    else if (m_accessor && m_accessor->canConvert(typeid(ValueType))) {
        // Try to convert value
        ValueType converted;
        if (m_accessor->convert(static_cast<void*>(&converted), typeid(ValueType))) {
            return converted;
        }
    }

    // Variant map or array to string conversion
    else if (isMap() || isArray()) {
        return ConvertTo<ValueType>::convertTo(*this);
    }

    // No conversion possible
    return defaultValue;
}

template <typename ValueType>
ValueType * Variant::ptr()
{
    if (m_accessor && typeid(ValueType) == m_accessor->type()) {
        return static_cast<AccessorValue<ValueType> *>(m_accessor)->ptr();
    } else {
        return nullptr;
    }
}

template <typename ValueType>
const ValueType * Variant::ptr() const
{
    if (m_accessor && typeid(ValueType) == m_accessor->type()) {
        return static_cast<const AccessorValue<ValueType> *>(m_accessor)->ptr();
    } else {
        return nullptr;
    }
}

} // namespace reflectionzeug
<commit_msg>Fix warning<commit_after>
#pragma once

#include <reflectionzeug/variant/Variant.h>

#include <reflectionzeug/property/AccessorValue.h>

namespace
{

template <typename ValueType>
struct ConvertTo
{
    static ValueType convertTo(const reflectionzeug::Variant & /*variant*/) {
        return ValueType();
    }
};

template <>
struct ConvertTo<std::string>
{
    static std::string convertTo(const reflectionzeug::Variant & variant) {
        return variant.toJSON();
    }
};

} // namespace

namespace reflectionzeug
{

template <typename ValueType>
Variant Variant::fromValue(const ValueType & value)
{
    Variant variant;
    variant.m_accessor = new AccessorValue<ValueType>(value);
    return variant;
}

template <typename ValueType>
bool Variant::hasType() const
{
    if (!m_accessor) {
        return false;
    }

    return typeid(ValueType) == m_accessor->type();
}

template <typename ValueType>
bool Variant::canConvert() const
{
    if (!m_accessor) {
        return false;
    }

    return m_accessor->canConvert(typeid(ValueType)) || hasType<ValueType>();
}

template <typename ValueType>
ValueType Variant::value(const ValueType & defaultValue) const
{
    // Type of variant is the wanted type
    if (m_accessor && typeid(ValueType) == m_accessor->type()) {
        return static_cast<AccessorValue<ValueType> *>(m_accessor)->value();
    }

    // Variant has to be converted
    else if (m_accessor && m_accessor->canConvert(typeid(ValueType))) {
        // Try to convert value
        ValueType converted;
        if (m_accessor->convert(static_cast<void*>(&converted), typeid(ValueType))) {
            return converted;
        }
    }

    // Variant map or array to string conversion
    else if (isMap() || isArray()) {
        return ConvertTo<ValueType>::convertTo(*this);
    }

    // No conversion possible
    return defaultValue;
}

template <typename ValueType>
ValueType * Variant::ptr()
{
    if (m_accessor && typeid(ValueType) == m_accessor->type()) {
        return static_cast<AccessorValue<ValueType> *>(m_accessor)->ptr();
    } else {
        return nullptr;
    }
}

template <typename ValueType>
const ValueType * Variant::ptr() const
{
    if (m_accessor && typeid(ValueType) == m_accessor->type()) {
        return static_cast<const AccessorValue<ValueType> *>(m_accessor)->ptr();
    } else {
        return nullptr;
    }
}

} // namespace reflectionzeug
<|endoftext|>


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

#include "Variable.hpp"
#include "iterators.hpp"
#include "FunctionContext.hpp"

#include "mtac/reference_resolver.hpp"
#include "mtac/Program.hpp"
#include "mtac/Function.hpp"
#include "mtac/Quadruple.hpp"
#include "mtac/Utils.hpp"

using namespace eddic;

mtac::Argument variant_cast(Offset source){
    if(auto* ptr = boost::get<int>(&source)){
        return *ptr;
    } else if(auto* ptr = boost::get<std::shared_ptr<Variable>>(&source)){
        return *ptr;
    } else {
        eddic_unreachable("Invalid source type");
    }
}

void mtac::resolve_references(mtac::Program& program){
    for(auto& function : program.functions){
        //This pass is run before basic blocks are extracted
        auto& statements = function.get_statements();

        auto it = iterate(statements);

        std::unordered_set<std::shared_ptr<Variable>> variables;

        while(it.has_next()){
            auto& quadruple = *it;
            auto op = quadruple.op;

            //x = (r)z => x = (ref(r))(z+offset(r))
            if((op == mtac::Operator::DOT || op == mtac::Operator::FDOT) && mtac::optional_is<std::shared_ptr<Variable>>(quadruple.arg1)){
                auto var = boost::get<std::shared_ptr<Variable>>(*quadruple.arg1);

                if(var->is_reference()){
                    if(var->type()->is_dynamic_array()){
                        auto ptr_temp = function.context->new_temporary(var->type());

                        quadruple.arg1 = ptr_temp;

                        it.insert_no_move(mtac::Quadruple(ptr_temp, var->reference(), mtac::Operator::DOT, variant_cast(var->reference_offset())));
                    } else {
                        auto index = *quadruple.arg2;
                        auto temp = function.context->new_temporary(INT);

                        //The reference itself is replaced by its pointed var
                        quadruple.arg1 = var->reference();

                        //The new offset is the sum of the old ones
                        quadruple.arg2 = temp;

                        it.insert_no_move(mtac::Quadruple(temp, index, mtac::Operator::ADD, variant_cast(var->reference_offset())));
                    }

                    continue;
                }
            }
            //(r)z = x => (ref(r))(z+offset(r)) = x
            else if((op == mtac::Operator::DOT_ASSIGN || op == mtac::Operator::DOT_FASSIGN)&& quadruple.result->is_reference()){
                auto var = quadruple.result;

                if(var->type()->is_dynamic_array()){
                    auto ptr_temp = function.context->new_temporary(var->type());

                    quadruple.result = ptr_temp;

                    it.insert_no_move(mtac::Quadruple(ptr_temp, var->reference(), mtac::Operator::DOT, variant_cast(var->reference_offset())));
                } else {
                    auto temp = function.context->new_temporary(INT);
                    auto index = *quadruple.arg1;

                    //The reference itself is replaced by its pointed var
                    quadruple.result = var->reference();

                    //The new offset is the sum of the old ones
                    quadruple.arg1 = temp;

                    it.insert_no_move(mtac::Quadruple(temp, index, mtac::Operator::ADD, variant_cast(var->reference_offset())));
                }

                continue;
            }

            //ref = x
            if(mtac::erase_result(quadruple.op)){
                auto result = quadruple.result;

                if(result && result->is_reference()){
                    //The first times a variable is encountered, it is its initialization
                    if(variables.find(result) == variables.end()){
                        variables.insert(result);

                        if(result->type()->is_dynamic_array()){
                            it.erase();
                            continue;
                        }
                    } else {
                        if(result->type() == FLOAT){
                            it.insert_after(mtac::Quadruple(result->reference(), variant_cast(result->reference_offset()), mtac::Operator::DOT_FASSIGN, result));
                        } else if(result->type()->is_pointer()){
                            it.insert_after(mtac::Quadruple(result->reference(), variant_cast(result->reference_offset()), mtac::Operator::DOT_PASSIGN, result));
                        } else {
                            it.insert_after(mtac::Quadruple(result->reference(), variant_cast(result->reference_offset()), mtac::Operator::DOT_ASSIGN, result));
                        }
                    }
                }
            }

            ++it;
        }
    }
}
<commit_msg>Resolve references in PDOT<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011-2012.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include "Variable.hpp"
#include "iterators.hpp"
#include "FunctionContext.hpp"

#include "mtac/reference_resolver.hpp"
#include "mtac/Program.hpp"
#include "mtac/Function.hpp"
#include "mtac/Quadruple.hpp"
#include "mtac/Utils.hpp"

using namespace eddic;

mtac::Argument variant_cast(Offset source){
    if(auto* ptr = boost::get<int>(&source)){
        return *ptr;
    } else if(auto* ptr = boost::get<std::shared_ptr<Variable>>(&source)){
        return *ptr;
    } else {
        eddic_unreachable("Invalid source type");
    }
}

void mtac::resolve_references(mtac::Program& program){
    for(auto& function : program.functions){
        //This pass is run before basic blocks are extracted
        auto& statements = function.get_statements();

        auto it = iterate(statements);

        std::unordered_set<std::shared_ptr<Variable>> variables;

        while(it.has_next()){
            auto& quadruple = *it;
            auto op = quadruple.op;

            //x = (r)z => x = (ref(r))(z+offset(r))
            if((op == mtac::Operator::DOT || op == mtac::Operator::FDOT || op == mtac::Operator::PDOT) && mtac::optional_is<std::shared_ptr<Variable>>(quadruple.arg1)){
                auto var = boost::get<std::shared_ptr<Variable>>(*quadruple.arg1);

                if(var->is_reference()){
                    if(var->type()->is_dynamic_array()){
                        auto ptr_temp = function.context->new_temporary(var->type());

                        quadruple.arg1 = ptr_temp;

                        it.insert_no_move(mtac::Quadruple(ptr_temp, var->reference(), mtac::Operator::DOT, variant_cast(var->reference_offset())));
                    } else {
                        auto index = *quadruple.arg2;
                        auto temp = function.context->new_temporary(INT);

                        //The reference itself is replaced by its pointed var
                        quadruple.arg1 = var->reference();

                        //The new offset is the sum of the old ones
                        quadruple.arg2 = temp;

                        it.insert_no_move(mtac::Quadruple(temp, index, mtac::Operator::ADD, variant_cast(var->reference_offset())));
                    }

                    continue;
                }
            }
            //(r)z = x => (ref(r))(z+offset(r)) = x
            else if((op == mtac::Operator::DOT_ASSIGN || op == mtac::Operator::DOT_FASSIGN)&& quadruple.result->is_reference()){
                auto var = quadruple.result;

                if(var->type()->is_dynamic_array()){
                    auto ptr_temp = function.context->new_temporary(var->type());

                    quadruple.result = ptr_temp;

                    it.insert_no_move(mtac::Quadruple(ptr_temp, var->reference(), mtac::Operator::DOT, variant_cast(var->reference_offset())));
                } else {
                    auto temp = function.context->new_temporary(INT);
                    auto index = *quadruple.arg1;

                    //The reference itself is replaced by its pointed var
                    quadruple.result = var->reference();

                    //The new offset is the sum of the old ones
                    quadruple.arg1 = temp;

                    it.insert_no_move(mtac::Quadruple(temp, index, mtac::Operator::ADD, variant_cast(var->reference_offset())));
                }

                continue;
            }

            //ref = x
            if(mtac::erase_result(quadruple.op)){
                auto result = quadruple.result;

                if(result && result->is_reference()){
                    //The first times a variable is encountered, it is its initialization
                    if(variables.find(result) == variables.end()){
                        variables.insert(result);

                        if(result->type()->is_dynamic_array()){
                            it.erase();
                            continue;
                        }
                    } else {
                        if(result->type() == FLOAT){
                            it.insert_after(mtac::Quadruple(result->reference(), variant_cast(result->reference_offset()), mtac::Operator::DOT_FASSIGN, result));
                        } else if(result->type()->is_pointer()){
                            it.insert_after(mtac::Quadruple(result->reference(), variant_cast(result->reference_offset()), mtac::Operator::DOT_PASSIGN, result));
                        } else {
                            it.insert_after(mtac::Quadruple(result->reference(), variant_cast(result->reference_offset()), mtac::Operator::DOT_ASSIGN, result));
                        }
                    }
                }
            }

            ++it;
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Convert test07 to new transactor.<commit_after><|endoftext|>


<commit_before>#ifndef ADDRESSES_HPP
#define ADDRESSES_HPP
#include <logical_address.h>

const LogicalAddress la_LSM(1, 0);
const LogicalAddress la_AGGREGATOR(1, 1);
const LogicalAddress la_RADIO(1, 2);
const LogicalAddress la_TEMPEX(1, 3);
const LogicalAddress la_TEMPIN(1, 4);
const LogicalAddress la_RTC(1, 5);
const LogicalAddress la_UV(1, 6);
const LogicalAddress la_LIGHT(1, 7);
const LogicalAddress la_GYRO(1, 8);
const LogicalAddress la_GPS(1, 9);
const LogicalAddress la_BARO(1, 10);
const LogicalAddress la_FILTER(1, 11);
const LogicalAddress la_BOOM(1, 12);
const LogicalAddress la_CAMERA(1, 13);

#endif
<commit_msg>Add battery to address list<commit_after>#ifndef ADDRESSES_HPP
#define ADDRESSES_HPP
#include <logical_address.h>

const LogicalAddress la_LSM(1, 0);
const LogicalAddress la_AGGREGATOR(1, 1);
const LogicalAddress la_RADIO(1, 2);
const LogicalAddress la_TEMPEX(1, 3);
const LogicalAddress la_TEMPIN(1, 4);
const LogicalAddress la_RTC(1, 5);
const LogicalAddress la_UV(1, 6);
const LogicalAddress la_LIGHT(1, 7);
const LogicalAddress la_GYRO(1, 8);
const LogicalAddress la_GPS(1, 9);
const LogicalAddress la_BARO(1, 10);
const LogicalAddress la_FILTER(1, 11);
const LogicalAddress la_BOOM(1, 12);
const LogicalAddress la_CAMERA(1, 13);
const LogicalAddress la_BATTERY(1, 14);

#endif
<|endoftext|>


<commit_before>/*
 * Point.cpp
 *
 *  Created on: Mar 28, 2014
 *      Author: icaro
 */

#include "Point.h"

Point::Point(){
	x=0, y=0;
}

Point::Point(float x, float y){
	this->x=x, this->y=y;
}

void Point::Set(Point point){
	x=point.GetX(); y=point.GetY();
}

void Point::Set(float x, float y){
	this->x=x,this->y=y;
}

Point Point::Add(Point other_point){
	return (Point(x+other_point.GetX(),y+other_point.GetY()));
}

Point Point::Add(float x, float y){
	return(Point(this->x+x,this->y+y));
}

Point Point::Subtract(Point other_point){
	return (Point(x-other_point.GetX(),y-other_point.GetY()));
}

Point Point::Multiply(float k){
	return(Point(k*x,k*y));
}

Point Point::Divide(float k){ //TODO: Apply exception in cases of division by 0
	if (k==0){
		std::cerr << "Cannot perform division by zero. Abort the program" << std::endl;
		exit(1);
	}
	return(Point(x/k,y/k));
}

float Point::DistanceTo(Point other_point){
	float x_distance = x - other_point.GetX();
	float y_distance = y - other_point.GetY();
	return(sqrt(pow(x_distance,2) + pow(y_distance,2)));
}

bool Point::IsOnTheLeftOf(Point other_point){
	return ((this->x < other_point.GetX()) ?  true : false);
}
bool Point::IsOnTheRightOf(Point other_point){
	return ((this->x > other_point.GetX()) ?  true : false);
}
bool Point::HasSameX(Point other_point){
	return ((this->x == other_point.GetX()) ?  true : false);
}
bool Point::IsAbove(Point other_point){
    return(this->y > other_point.GetY() ? true:false);
}
bool Point::IsLowerThan(){
    return(this->y < other_point.GetY() ? true:false);
}
bool Point::HasSameY(Point other_point){
	return ((this->y == other_point.GetY()) ?  true : false);
}

bool Point::IsEqualTo(Point other_point){
	return (HasSameX(other_point) && HasSameY(other_point));
}

void Point::Move(float distance, float angle){
	x += (distance*cos(angle));
	y += (distance*sin(angle));
}

void Point::MoveXY(float x, float y){
	this->x += x;
	this->y += y;
}
<commit_msg>Overloaded operators for points<commit_after>/*
 * Point.cpp
 *
 *  Created on: Mar 28, 2014
 *      Author: icaro
 */

#include "Point.h"

Point::Point(){
	x=0, y=0;
}

Point::Point(float x, float y){
	this->x=x, this->y=y;
}

void Point::Set(Point point){
	x=point.GetX(); y=point.GetY();
}

void Point::Set(float x, float y){
	this->x=x,this->y=y;
}

Point operator+(Point& rhs) {
    return (Point(x + rhs.x,y + rhs.y));
}

Point operator-(Point& rhs) {
    return (Point(x - rhs.x,y - rhs.y));
}

Point operator*(float rhs) {
    return (Point(x*rhs,y*rhs));
}

Point operator/(float rhs) { //Look out, do not divide by 0
    return (Point(x/rhs,y/rhs));
}

float Point::DistanceTo(Point other_point){
	float x_distance = x - other_point.GetX();
	float y_distance = y - other_point.GetY();
	return(sqrt(pow(x_distance,2) + pow(y_distance,2)));
}

bool Point::IsOnTheLeftOf(Point other_point){
	return ((this->x < other_point.GetX()) ?  true : false);
}
bool Point::IsOnTheRightOf(Point other_point){
	return ((this->x > other_point.GetX()) ?  true : false);
}
bool Point::HasSameX(Point other_point){
	return ((this->x == other_point.GetX()) ?  true : false);
}
bool Point::IsAbove(Point other_point){
    return(this->y > other_point.GetY() ? true:false);
}
bool Point::IsLowerThan(){
    return(this->y < other_point.GetY() ? true:false);
}
bool Point::HasSameY(Point other_point){
	return ((this->y == other_point.GetY()) ?  true : false);
}

bool Point::IsEqualTo(Point other_point){
	return (HasSameX(other_point) && HasSameY(other_point));
}

void Point::Move(float distance, float angle){
	x += (distance*cos(angle));
	y += (distance*sin(angle));
}

void Point::MoveXY(float x, float y){
	this->x += x;
	this->y += y;
}
<|endoftext|>


<commit_before>// -*- Mode: C++; tab-width: 2; -*-
// vi: set ts=2:
//
// $Id: SmilesParser_test.C,v 1.5 2003/05/27 14:04:32 oliver Exp $
//

#include <BALL/CONCEPT/classTest.h>

///////////////////////////

#include <BALL/STRUCTURE/smilesParser.h>
#include <BALL/KERNEL/PTE.h>

#include <fstream>
#include <iostream>
#include <algorithm>
#include <iterator>

///////////////////////////

using namespace BALL;

typedef std::map<String, Size> Formula;
typedef std::pair<String, Formula> Line;

std::ostream& operator << (std::ostream& os, const std::pair<BALL::String, Size>& p)
{
	return os << p.first << p.second;
}

std::ostream& operator << (std::ostream& os, const std::map<String, Size>& f)
{
	std::map<String, Size>::const_iterator it(f.begin());
	for (; it != f.end(); it++)
	{
		os << it->first << "/" << it->second << " ";
	}
	return os;
}

Formula computeFormula(const System& s)
{
	Formula f;
	AtomConstIterator atom(s.beginAtom());
	for (; atom != s.endAtom(); ++atom)
	{
		f[atom->getElement().getSymbol()]++;
	}
	return f;
}

Line readSmilesLine(std::istream& is)
{
	String line;
	line.getline(is);
	std::pair<String, Formula> s;

	if (line != "")
	{
		s.first = line.getField(0);
		for (Position i = 1; i < line.countFields(); i += 2)
		{
			s.second[line.getField(i)] = line.getField(i + 1).toUnsignedInt();
		}
	}
	return s;
}

START_TEST(SmilesParser, "$Id: SmilesParser_test.C,v 1.5 2003/05/27 14:04:32 oliver Exp $")

/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////

SmilesParser sp;
CHECK(C)
	sp.parse("C");
	TEST_EQUAL(sp.getSystem().countAtoms(), 5)

	ABORT_IF(sp.getSystem().countAtoms() != 5)
	const Atom& atom = *sp.getSystem().getAtom(0);
	TEST_EQUAL(atom.getElement(), PTE[Element::C])
	TEST_EQUAL(atom.countBonds(), 4)
RESULT
/*

CHECK([C])
	sp.parse("[C]");
	TEST_EQUAL(sp.getSystem().countAtoms(), 1)

	ABORT_IF(sp.getSystem().countAtoms() != 1)
	const Atom& atom = *sp.getSystem().getAtom(0);
	TEST_EQUAL(atom.getElement(), PTE[Element::C])
	TEST_EQUAL(atom.countBonds(), 0)
RESULT

CHECK(parse errors)
	TEST_EXCEPTION(Exception::ParseError, sp.parse("X"))
	TEST_EXCEPTION(Exception::ParseError, sp.parse("+"))
	TEST_EXCEPTION(Exception::ParseError, sp.parse("+4"))
	TEST_EXCEPTION(Exception::ParseError, sp.parse("C+"))
RESULT

CHECK(example library)
	std::ifstream is("data/SmilesParser_test.txt");
	std::pair<String, Formula> smiles;
	while (is.good())
	{
		smiles = readSmilesLine(is);
		STATUS(smiles.first << "/" << smiles.second)
		if (smiles.first == "")
		{
			break;
		}
		sp.parse(smiles.first);
		TEST_EQUAL(computeFormula(sp.getSystem()), smiles.second)
	}

RESULT
*/
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////

END_TEST
<commit_msg>fixed: removed comments added for debugging<commit_after>// -*- Mode: C++; tab-width: 2; -*-
// vi: set ts=2:
//
// $Id: SmilesParser_test.C,v 1.6 2003/05/28 16:51:57 oliver Exp $
//

#include <BALL/CONCEPT/classTest.h>

///////////////////////////

#include <BALL/STRUCTURE/smilesParser.h>
#include <BALL/KERNEL/PTE.h>

#include <fstream>
#include <iostream>
#include <algorithm>
#include <iterator>

///////////////////////////

using namespace BALL;

typedef std::map<String, Size> Formula;
typedef std::pair<String, Formula> Line;

std::ostream& operator << (std::ostream& os, const std::pair<BALL::String, Size>& p)
{
	return os << p.first << p.second;
}

std::ostream& operator << (std::ostream& os, const std::map<String, Size>& f)
{
	std::map<String, Size>::const_iterator it(f.begin());
	for (; it != f.end(); it++)
	{
		os << it->first << "/" << it->second << " ";
	}
	return os;
}

Formula computeFormula(const System& s)
{
	Formula f;
	AtomConstIterator atom(s.beginAtom());
	for (; atom != s.endAtom(); ++atom)
	{
		f[atom->getElement().getSymbol()]++;
	}
	return f;
}

Line readSmilesLine(std::istream& is)
{
	String line;
	line.getline(is);
	std::pair<String, Formula> s;

	if (line != "")
	{
		s.first = line.getField(0);
		for (Position i = 1; i < line.countFields(); i += 2)
		{
			s.second[line.getField(i)] = line.getField(i + 1).toUnsignedInt();
		}
	}
	return s;
}

START_TEST(SmilesParser, "$Id: SmilesParser_test.C,v 1.6 2003/05/28 16:51:57 oliver Exp $")

/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////

SmilesParser sp;
CHECK(C)
	sp.parse("C");
	TEST_EQUAL(sp.getSystem().countAtoms(), 5)

	ABORT_IF(sp.getSystem().countAtoms() != 5)
	const Atom& atom = *sp.getSystem().getAtom(0);
	TEST_EQUAL(atom.getElement(), PTE[Element::C])
	TEST_EQUAL(atom.countBonds(), 4)
RESULT

CHECK([C])
	sp.parse("[C]");
	TEST_EQUAL(sp.getSystem().countAtoms(), 1)

	ABORT_IF(sp.getSystem().countAtoms() != 1)
	const Atom& atom = *sp.getSystem().getAtom(0);
	TEST_EQUAL(atom.getElement(), PTE[Element::C])
	TEST_EQUAL(atom.countBonds(), 0)
RESULT

CHECK(parse errors)
	TEST_EXCEPTION(Exception::ParseError, sp.parse("X"))
	TEST_EXCEPTION(Exception::ParseError, sp.parse("+"))
	TEST_EXCEPTION(Exception::ParseError, sp.parse("+4"))
	TEST_EXCEPTION(Exception::ParseError, sp.parse("C+"))
RESULT

CHECK(example library)
	std::ifstream is("data/SmilesParser_test.txt");
	std::pair<String, Formula> smiles;
	while (is.good())
	{
		smiles = readSmilesLine(is);
		STATUS(smiles.first << "/" << smiles.second)
		if (smiles.first == "")
		{
			break;
		}
		sp.parse(smiles.first);
		TEST_EQUAL(computeFormula(sp.getSystem()), smiles.second)
	}

RESULT

/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////

END_TEST
<|endoftext|>


<commit_before>#include <catch.hpp>
#include <luwra.hpp>

#include <cstring>
#include <string>
#include <utility>
#include <type_traits>

#if LUA_VERSION_NUM >= 503

template <typename I>
struct NumericTest {
	static
	void test(lua_State* state) {
		const I max_value = std::numeric_limits<I>::max();
		const I min_value = std::numeric_limits<I>::lowest();
		const I avg_value = (max_value + min_value) / 2;

		// Largest value
		CHECK((luwra::push(state, max_value) == 1));
		CHECK((luwra::read<I>(state, -1) == max_value));

		// Lowest value
		CHECK((luwra::push(state, min_value) == 1));
		CHECK((luwra::read<I>(state, -1) == min_value));

		// Average value
		CHECK((luwra::push(state, avg_value) == 1));
		CHECK((luwra::read<I>(state, -1) == avg_value));
	}
};

TEST_CASE("NumberLimits") {
	luwra::StateWrapper state;

	// Integer-based types
	NumericTest<signed char>::test(state);
	NumericTest<unsigned char>::test(state);
	NumericTest<signed short>::test(state);
	NumericTest<unsigned short>::test(state);
	NumericTest<signed int>::test(state);
	NumericTest<unsigned int>::test(state);
	NumericTest<signed long int>::test(state);
	NumericTest<unsigned long int>::test(state);
	NumericTest<signed long long int>::test(state);
	NumericTest<unsigned long long int>::test(state);

	// Number-based types
	NumericTest<float>::test(state);
	NumericTest<double>::test(state);
	NumericTest<long double>::test(state);
}

#endif /* LUA_VERSION_NUM >= 503 */

TEST_CASE("Numbers") {
	luwra::StateWrapper state;

	REQUIRE(luwra::push(state, 1337) == 1);
	REQUIRE(luwra::push(state, 13.37) == 1);

	REQUIRE(luwra::read<int>(state, -2) == 1337);
	REQUIRE(luwra::read<float>(state, -1) == 13.37f);
}

TEST_CASE("Strings") {
	luwra::StateWrapper state;

	const char* test_cstr = "Luwra Test String";
	std::string test_str(test_cstr);

	// Safety first
	REQUIRE(test_str == test_cstr);

	// Push both strings
	REQUIRE(luwra::push(state, test_cstr) == 1);
	REQUIRE(luwra::push(state, test_str) == 1);

	// They must be equal to Lua
	REQUIRE(luwra::equal(state, -1, -2));

	// Extraction as C string must not change the string's value
	const char* l_cstr1 = luwra::read<const char*>(state, -1);
	const char* l_cstr2 = luwra::read<const char*>(state, -2);

	REQUIRE(std::strcmp(test_cstr,        l_cstr1) == 0);
	REQUIRE(std::strcmp(test_cstr,        l_cstr2) == 0);
	REQUIRE(std::strcmp(test_str.c_str(), l_cstr1) == 0);
	REQUIRE(std::strcmp(test_str.c_str(), l_cstr2) == 0);
	REQUIRE(std::strcmp(l_cstr1,          l_cstr2) == 0);

	// Extraction as C++ string must not change the string's value
	std::string l_str1 = luwra::read<std::string>(state, -1);
	std::string l_str2 = luwra::read<std::string>(state, -2);

	REQUIRE(l_str1   == test_cstr);
	REQUIRE(l_str2   == test_cstr);
	REQUIRE(test_str == l_str1);
	REQUIRE(test_str == l_str2);
	REQUIRE(l_str1   == l_str2);
}

TEST_CASE("Tuples") {
	luwra::StateWrapper state;

	int a = 13;
	std::string b("Hello");
	float c = 0.37;

	// Push normal tuple
	auto tuple = std::make_tuple(a, b, c);
	REQUIRE(luwra::push(state, tuple) == 3);

	// Push nested tuple
	auto tuple_nested = std::make_tuple(a, b, c, tuple);
	REQUIRE(luwra::push(state, tuple_nested) == 6);
}

TEST_CASE("Boolean") {
	luwra::StateWrapper state;

	bool value = true;

	REQUIRE(luwra::push(state, value) == 1);
	REQUIRE(luwra::read<bool>(state, -1) == value);
}

TEST_CASE("Pushable") {
	luwra::StateWrapper state;

	luwra::Pushable pushable(1337);
	REQUIRE(luwra::push(state, pushable) == 1);

	REQUIRE(luwra::read<int>(state, -1) == 1337);
}
<commit_msg>Remove numeric value tests completely<commit_after>#include <catch.hpp>
#include <luwra.hpp>

#include <cstring>
#include <string>
#include <utility>
#include <type_traits>

#if false

template <typename I>
struct NumericTest {
	static
	void test(lua_State* state) {
		const I max_value = std::numeric_limits<I>::max();
		const I min_value = std::numeric_limits<I>::lowest();
		const I avg_value = (max_value + min_value) / 2;

		// Largest value
		CHECK((luwra::push(state, max_value) == 1));
		CHECK((luwra::read<I>(state, -1) == max_value));

		// Lowest value
		CHECK((luwra::push(state, min_value) == 1));
		CHECK((luwra::read<I>(state, -1) == min_value));

		// Average value
		CHECK((luwra::push(state, avg_value) == 1));
		CHECK((luwra::read<I>(state, -1) == avg_value));
	}
};

TEST_CASE("NumberLimits") {
	luwra::StateWrapper state;

	// Integer-based types
	NumericTest<signed char>::test(state);
	NumericTest<unsigned char>::test(state);
	NumericTest<signed short>::test(state);
	NumericTest<unsigned short>::test(state);
	NumericTest<signed int>::test(state);
	NumericTest<unsigned int>::test(state);
	NumericTest<signed long int>::test(state);
	NumericTest<unsigned long int>::test(state);
	NumericTest<signed long long int>::test(state);
	NumericTest<unsigned long long int>::test(state);

	// Number-based types
	NumericTest<float>::test(state);
	NumericTest<double>::test(state);
	NumericTest<long double>::test(state);
}

#endif /* false */

TEST_CASE("Numbers") {
	luwra::StateWrapper state;

	REQUIRE(luwra::push(state, 1337) == 1);
	REQUIRE(luwra::push(state, 13.37) == 1);

	REQUIRE(luwra::read<int>(state, -2) == 1337);
	REQUIRE(luwra::read<float>(state, -1) == 13.37f);
}

TEST_CASE("Strings") {
	luwra::StateWrapper state;

	const char* test_cstr = "Luwra Test String";
	std::string test_str(test_cstr);

	// Safety first
	REQUIRE(test_str == test_cstr);

	// Push both strings
	REQUIRE(luwra::push(state, test_cstr) == 1);
	REQUIRE(luwra::push(state, test_str) == 1);

	// They must be equal to Lua
	REQUIRE(luwra::equal(state, -1, -2));

	// Extraction as C string must not change the string's value
	const char* l_cstr1 = luwra::read<const char*>(state, -1);
	const char* l_cstr2 = luwra::read<const char*>(state, -2);

	REQUIRE(std::strcmp(test_cstr,        l_cstr1) == 0);
	REQUIRE(std::strcmp(test_cstr,        l_cstr2) == 0);
	REQUIRE(std::strcmp(test_str.c_str(), l_cstr1) == 0);
	REQUIRE(std::strcmp(test_str.c_str(), l_cstr2) == 0);
	REQUIRE(std::strcmp(l_cstr1,          l_cstr2) == 0);

	// Extraction as C++ string must not change the string's value
	std::string l_str1 = luwra::read<std::string>(state, -1);
	std::string l_str2 = luwra::read<std::string>(state, -2);

	REQUIRE(l_str1   == test_cstr);
	REQUIRE(l_str2   == test_cstr);
	REQUIRE(test_str == l_str1);
	REQUIRE(test_str == l_str2);
	REQUIRE(l_str1   == l_str2);
}

TEST_CASE("Tuples") {
	luwra::StateWrapper state;

	int a = 13;
	std::string b("Hello");
	float c = 0.37;

	// Push normal tuple
	auto tuple = std::make_tuple(a, b, c);
	REQUIRE(luwra::push(state, tuple) == 3);

	// Push nested tuple
	auto tuple_nested = std::make_tuple(a, b, c, tuple);
	REQUIRE(luwra::push(state, tuple_nested) == 6);
}

TEST_CASE("Boolean") {
	luwra::StateWrapper state;

	bool value = true;

	REQUIRE(luwra::push(state, value) == 1);
	REQUIRE(luwra::read<bool>(state, -1) == value);
}

TEST_CASE("Pushable") {
	luwra::StateWrapper state;

	luwra::Pushable pushable(1337);
	REQUIRE(luwra::push(state, pushable) == 1);

	REQUIRE(luwra::read<int>(state, -1) == 1337);
}
<|endoftext|>