<commit_before>#include "headers/mainwindow.h"
#include "headers/cryptogame.h"
#include "ui_mainwindow.h"
#include "QPushButton"
#include <QLayoutItem>
#include <QMessageBox>
#include "headers/buttonarray.h"
#include "headers/labelarray.h"

#include "iostream" //for debugging

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
    //delete hashAlg;
}

void MainWindow::on_pushButton_clicked()
{
    std::cout<<"Start the game."<<std::endl;

    //Delete all buttons in the layoutForButtons if there are existing buttons in the layout
    while(ui->layoutForButtons->count() > 0 || ui->layoutForLabels->count() > 0){
        if(ui->layoutForButtons->count() > 0){
        QLayoutItem *button = ui->layoutForButtons->takeAt(0);
        delete button->widget();
        delete button;
        }
        if(ui->layoutForLabels->count() > 0){
        QLayoutItem *label = ui->layoutForLabels->takeAt(0);
        delete label->widget();
        delete label;
        }
    }

    agame = new cryptogame();
    QString q = QString::fromStdString(agame->getEncryptedMessage());
    //ui->label->setText(q);
    LabelArray *lptr = new LabelArray(q, ui->tabWidget);
    ButtonArray *ptr = new ButtonArray(q, ui->tabWidget, agame);
    for(int i=0; i<q.size(); i++){
        ui->layoutForLabels->addWidget(lptr->get(i));
        ui->layoutForButtons->addWidget(ptr->get(i));
    }
    guessedWord.clear();
    guessedWord = ptr->checkGuess();

}

void MainWindow::on_pushButton_2_clicked()
{

    QString temp = guessedWord;
    std::string send = temp.toStdString();

    bool win = agame->sendCurrentGuess(send);

    //Debugging stuffs
    std::cout<<win<<std::endl;
    std::cout<<temp.toStdString()<<std::endl;
    std::cout<<agame->d_message<<std::endl;

}

void MainWindow::on_pushButton_3_clicked()
{
    //Somehow give a hint to the player.
    QMessageBox winningMessage;
    //Note: there are tabs in the QString in the next sentence
    winningMessage.setText("Here's a hint: There are no hints                                             ");
    winningMessage.exec();
   // ui->textEdit->setText("Here's a hint: There are no hints");
}

void MainWindow::on_factorPrimesButton_clicked()
{
    //reset label text
    ui->resultLabel->setText(QString::fromStdString("Result:"));
    ui->timeLabel->setText(QString::fromStdString("Time: "));
    ui->resultLabel->repaint();
    ui->timeLabel->repaint();

    //set algorithm
    int algChoice = ui->factorAlgChooser->currentIndex();
    Factor* pf;

    switch(algChoice) {
    case 0:
        pf = new BruteForceFactor();
        break;
    case 1:
        //Quadratic sieve here
        break;
    }

    QElapsedTimer timer;

    mpz_class composite;
    string s = ui->compositeTextField->text().toStdString();
    composite.set_str(s, 10);

    timer.start();
    pf->factor(composite);
    long elapsed = timer.elapsed();

    string s2 = "Time: " + QString::number(elapsed).toStdString() + " ms";
    ui->timeLabel->setText(QString::fromStdString(s2));

    s = "Result: " + pf->p1.get_str(10) + " * " + pf->p2.get_str(10);
    ui->resultLabel->setText(QString::fromStdString(s));
    delete pf;
}

void MainWindow::on_random_composite_clicked()
{
    mpz_class composite, p, q;
    GeneratePrimes gp = GeneratePrimes();
    p = gp.readRandomPrime((char*)"primes.txt");
    q = gp.readRandomPrime((char*)"primes.txt");
    composite = p * q;
    string s = composite.get_str(10);
    ui->compositeTextField->setText(QString::fromStdString(s));
}

void MainWindow::on_hashButton_clicked()
{
    switch(ui->hashComboBox->currentIndex()) {
    case 0:
        hashAlg = new Md5();
        break;
    case 1:
        hashAlg = new Sha512();
        break;
    case 2:
        hashAlg = new Pbkdf2();
        break;
    }

    hashAlg->setPlaintext(ui->plaintextField->text());

    if(ui->saltField->text() != "") { //if not empty
        hashAlg->setSalt(ui->saltField->text());
    }
    hashAlg->compute();
    digest = hashAlg->getDigest();
    ui->digestField->setText(digest);

    //remove salt field so that crack doesn't "cheat"
    //i.e. cracking algorithm doesnt know salt value
    hashAlg->salt = "";
}

void MainWindow::on_randomSaltButton_clicked()
{
    Hash h;
    h.generateSalt(16);
    ui->saltField->setText(h.getSalt());
}

void MainWindow::on_crackButton_clicked()
{
    //reset label text
    ui->crackTimeLabel->setText("Time: ");
    ui->crackTimeLabel->repaint();
    ui->crackedField->setText("");
    ui->crackedField->repaint();

    QElapsedTimer timer;
    long elapsed;
    bool success;
    Crack* c;
    if(hashAlg == NULL) {
    	return;
    }

    switch(ui->crackComboBox->currentIndex()) {
    case 0:
        {int maxLength = ui->charCountSpinBox->text().toInt();
        c = new BruteForceCrack(hashAlg,bruteForceAlphabet(), maxLength);
        break;}

    case 1:
        {c = new DictionaryCrack(hashAlg, "../dictionary.txt");
        dictionaryOptions(c);
        break;}
    }

    c->digest = digest.toStdString();

    timer.start();
    c->reverse();
    success = c->getPlaintext().length();
    elapsed = timer.elapsed();

    //if
    if(success) {
        ui->crackedField->setText(c->getPlaintext());
    } else {
        ui->crackedField->setText("\"Uncrackable!!\"");
    }

    string s = "Time: " + QString::number(elapsed).toStdString() + " ms";
    ui->crackTimeLabel->setText(QString::fromStdString(s));
}

std::string MainWindow::bruteForceAlphabet() {

    std::string alph = " ";//weird bug "fix"

    if(ui->customCheckBox->isChecked()) {
        return ui->alphabetField->text().toStdString();
    }
    if(ui->lettersCheckBox->isChecked()) {
        alph += "abcdefghijklmnopqrstuvwxyz";
    }
    if(ui->upCaseCheckBox->isChecked()) {
        alph += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    }
    if(ui->numbersCheckBox->isChecked()) {
        alph += "1234567890";
    }
    if(ui->symbolsCheckBox->isChecked()) {
        alph += "`~!@#$%^&*()_+-=,.<>/?'[]{}";
    }
    return alph;
}

void MainWindow::dictionaryOptions(Crack* d) {

    unsigned int numWords = ui->wordCountSpinBox->text().toInt();
    unsigned int appendedDigits = 0;
    if(ui->appendCheckBox->isChecked()) {
        appendedDigits = ui->digitCountSpinBox->text().toInt();
    }
    unsigned int prependedDigits = 0;
    if(ui->prependCheckBox->isChecked()) {
        prependedDigits = ui->digitCountSpinBox->text().toInt();
    }
    unsigned int symbols = 0;
    unsigned int cap = false;

    d->setOptions(numWords,appendedDigits,prependedDigits,symbols,cap);
}

void MainWindow::on_drawFactoring_clicked()
{
    //generate data
    int beginDigits = ui->startDigitsSpinBox->text().toInt();
    int count = ui->dataPointsSpinBox->text().toInt();
    std::vector<mpz_class> comps = GenerateData::composites(beginDigits, count);
    factorDataPoints = GenerateData::factor(comps, new BruteForceFactor);

    //draw points
    g = new GraphWindow(ui->factoringGraphicsView, factorDataPoints);
    g->vSize = 600;
    g->hSize = 600;

    if(ui->factorLogScaleCheckBox->isChecked()) {
        g->logScaleDraw();
    } else {
        g->draw();
    }
    g->addLabels("Milliseconds", "Number of digits");

    g->view->show();
}

void MainWindow::on_plotCrackButton_clicked()
{
    //grab hashing and cracking algorithms

    switch(ui->hashComboBox->currentIndex()) {
    case 0:
        hashAlg = new Md5();
        break;
    case 1:
        hashAlg = new Sha512();
        break;
    case 2:
        hashAlg = new Pbkdf2();
        break;
    }

    Crack* c;
    if(hashAlg == NULL) {
        return;
    }

    switch(ui->crackComboBox->currentIndex()) {
    case 0:
        {int maxLength = ui->charCountSpinBox->text().toInt();
        c = new BruteForceCrack(hashAlg,bruteForceAlphabet(), maxLength);
        break;}

    case 1:
        {c = new DictionaryCrack(hashAlg, "../dictionary.txt");
        break;}
    }

    //generate data
    int beginChars = ui->charCountSpinBox_2->text().toInt();
    int count = ui->crackPointCountSpinBox->text().toInt();
    std::vector<std::string> strings = GenerateData::plaintexts(beginChars, count);
    std::vector<std::string> digests = GenerateData::getHashes(strings, hashAlg);
    crackDataPoints = GenerateData::crack(digests, c);

    //begin graphing
    g = new GraphWindow(ui->crackGraphicsView, crackDataPoints);
    g->vSize = 600;
    g->hSize = 600;

    if(ui->hashLogScaleCheckBox->isChecked()) {
        g->logScaleDraw();
    } else {
        g->draw();
    }
    g->addLabels("Milliseconds", "Number of characters");

    g->view->show();
}

void MainWindow::on_hashLogScaleCheckBox_clicked()
{
    if(g == NULL) {
        std::cout << "graphwindow object not initialized. No action to take." << std::endl;
        return;
    }
    if(crackDataPoints.size() == 0) {
        std::cout << "No points to graph." << std::endl;
        return;
    }

    g = new GraphWindow(ui->crackGraphicsView, crackDataPoints);
    g->vSize = 600;
    g->hSize = 600;

    if(ui->hashLogScaleCheckBox->isChecked()) {
        g->logScaleDraw();
    } else {
        g->draw();
    }
    g->addLabels("Milliseconds", "Number of characters");

    g->view->show();

}

void MainWindow::on_factorLogScaleCheckBox_clicked()
{
    if(g == NULL) {
        std::cout << "graphwindow object not initialized. No action to take." << std::endl;
        return;
    }
    if(factorDataPoints.size() == 0) {
        std::cout << "No points to graph." << std::endl;
        return;
    }

    g = new GraphWindow(ui->factoringGraphicsView, factorDataPoints);
    g->vSize = 600;
    g->hSize = 600;

    if(ui->factorLogScaleCheckBox->isChecked()) {
        g->logScaleDraw();
    } else {
        g->draw();
    }
    g->addLabels("Milliseconds", "Number of characters");

    g->view->show();
}
<commit_msg>emptied the on_pushButton_2_clicked() function<commit_after>#include "headers/mainwindow.h"
#include "headers/cryptogame.h"
#include "ui_mainwindow.h"
#include "QPushButton"
#include <QLayoutItem>
#include <QMessageBox>
#include "headers/buttonarray.h"
#include "headers/labelarray.h"

#include "iostream" //for debugging

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
    //delete hashAlg;
}

void MainWindow::on_pushButton_clicked()
{
    std::cout<<"Start the game."<<std::endl;

    //Delete all buttons in the layoutForButtons if there are existing buttons in the layout
    while(ui->layoutForButtons->count() > 0 || ui->layoutForLabels->count() > 0){
        if(ui->layoutForButtons->count() > 0){
        QLayoutItem *button = ui->layoutForButtons->takeAt(0);
        delete button->widget();
        delete button;
        }
        if(ui->layoutForLabels->count() > 0){
        QLayoutItem *label = ui->layoutForLabels->takeAt(0);
        delete label->widget();
        delete label;
        }
    }

    agame = new cryptogame();
    QString q = QString::fromStdString(agame->getEncryptedMessage());
    //ui->label->setText(q);
    LabelArray *lptr = new LabelArray(q, ui->tabWidget);
    ButtonArray *ptr = new ButtonArray(q, ui->tabWidget, agame);
    for(int i=0; i<q.size(); i++){
        ui->layoutForLabels->addWidget(lptr->get(i));
        ui->layoutForButtons->addWidget(ptr->get(i));
    }
    guessedWord.clear();
    guessedWord = ptr->checkGuess();

}

void MainWindow::on_pushButton_2_clicked(){}

void MainWindow::on_pushButton_3_clicked()
{
    //Somehow give a hint to the player.
    QMessageBox winningMessage;
    //Note: there are tabs in the QString in the next sentence
    winningMessage.setText("Here's a hint: There are no hints                                             ");
    winningMessage.exec();
   // ui->textEdit->setText("Here's a hint: There are no hints");
}

void MainWindow::on_factorPrimesButton_clicked()
{
    //reset label text
    ui->resultLabel->setText(QString::fromStdString("Result:"));
    ui->timeLabel->setText(QString::fromStdString("Time: "));
    ui->resultLabel->repaint();
    ui->timeLabel->repaint();

    //set algorithm
    int algChoice = ui->factorAlgChooser->currentIndex();
    Factor* pf;

    switch(algChoice) {
    case 0:
        pf = new BruteForceFactor();
        break;
    case 1:
        //Quadratic sieve here
        break;
    }

    QElapsedTimer timer;

    mpz_class composite;
    string s = ui->compositeTextField->text().toStdString();
    composite.set_str(s, 10);

    timer.start();
    pf->factor(composite);
    long elapsed = timer.elapsed();

    string s2 = "Time: " + QString::number(elapsed).toStdString() + " ms";
    ui->timeLabel->setText(QString::fromStdString(s2));

    s = "Result: " + pf->p1.get_str(10) + " * " + pf->p2.get_str(10);
    ui->resultLabel->setText(QString::fromStdString(s));
    delete pf;
}

void MainWindow::on_random_composite_clicked()
{
    mpz_class composite, p, q;
    GeneratePrimes gp = GeneratePrimes();
    p = gp.readRandomPrime((char*)"primes.txt");
    q = gp.readRandomPrime((char*)"primes.txt");
    composite = p * q;
    string s = composite.get_str(10);
    ui->compositeTextField->setText(QString::fromStdString(s));
}

void MainWindow::on_hashButton_clicked()
{
    switch(ui->hashComboBox->currentIndex()) {
    case 0:
        hashAlg = new Md5();
        break;
    case 1:
        hashAlg = new Sha512();
        break;
    case 2:
        hashAlg = new Pbkdf2();
        break;
    }

    hashAlg->setPlaintext(ui->plaintextField->text());

    if(ui->saltField->text() != "") { //if not empty
        hashAlg->setSalt(ui->saltField->text());
    }
    hashAlg->compute();
    digest = hashAlg->getDigest();
    ui->digestField->setText(digest);

    //remove salt field so that crack doesn't "cheat"
    //i.e. cracking algorithm doesnt know salt value
    hashAlg->salt = "";
}

void MainWindow::on_randomSaltButton_clicked()
{
    Hash h;
    h.generateSalt(16);
    ui->saltField->setText(h.getSalt());
}

void MainWindow::on_crackButton_clicked()
{
    //reset label text
    ui->crackTimeLabel->setText("Time: ");
    ui->crackTimeLabel->repaint();
    ui->crackedField->setText("");
    ui->crackedField->repaint();

    QElapsedTimer timer;
    long elapsed;
    bool success;
    Crack* c;
    if(hashAlg == NULL) {
    	return;
    }

    switch(ui->crackComboBox->currentIndex()) {
    case 0:
        {int maxLength = ui->charCountSpinBox->text().toInt();
        c = new BruteForceCrack(hashAlg,bruteForceAlphabet(), maxLength);
        break;}

    case 1:
        {c = new DictionaryCrack(hashAlg, "../dictionary.txt");
        dictionaryOptions(c);
        break;}
    }

    c->digest = digest.toStdString();

    timer.start();
    c->reverse();
    success = c->getPlaintext().length();
    elapsed = timer.elapsed();

    //if
    if(success) {
        ui->crackedField->setText(c->getPlaintext());
    } else {
        ui->crackedField->setText("\"Uncrackable!!\"");
    }

    string s = "Time: " + QString::number(elapsed).toStdString() + " ms";
    ui->crackTimeLabel->setText(QString::fromStdString(s));
}

std::string MainWindow::bruteForceAlphabet() {

    std::string alph = " ";//weird bug "fix"

    if(ui->customCheckBox->isChecked()) {
        return ui->alphabetField->text().toStdString();
    }
    if(ui->lettersCheckBox->isChecked()) {
        alph += "abcdefghijklmnopqrstuvwxyz";
    }
    if(ui->upCaseCheckBox->isChecked()) {
        alph += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    }
    if(ui->numbersCheckBox->isChecked()) {
        alph += "1234567890";
    }
    if(ui->symbolsCheckBox->isChecked()) {
        alph += "`~!@#$%^&*()_+-=,.<>/?'[]{}";
    }
    return alph;
}

void MainWindow::dictionaryOptions(Crack* d) {

    unsigned int numWords = ui->wordCountSpinBox->text().toInt();
    unsigned int appendedDigits = 0;
    if(ui->appendCheckBox->isChecked()) {
        appendedDigits = ui->digitCountSpinBox->text().toInt();
    }
    unsigned int prependedDigits = 0;
    if(ui->prependCheckBox->isChecked()) {
        prependedDigits = ui->digitCountSpinBox->text().toInt();
    }
    unsigned int symbols = 0;
    unsigned int cap = false;

    d->setOptions(numWords,appendedDigits,prependedDigits,symbols,cap);
}

void MainWindow::on_drawFactoring_clicked()
{
    //generate data
    int beginDigits = ui->startDigitsSpinBox->text().toInt();
    int count = ui->dataPointsSpinBox->text().toInt();
    std::vector<mpz_class> comps = GenerateData::composites(beginDigits, count);
    factorDataPoints = GenerateData::factor(comps, new BruteForceFactor);

    //draw points
    g = new GraphWindow(ui->factoringGraphicsView, factorDataPoints);
    g->vSize = 600;
    g->hSize = 600;

    if(ui->factorLogScaleCheckBox->isChecked()) {
        g->logScaleDraw();
    } else {
        g->draw();
    }
    g->addLabels("Milliseconds", "Number of digits");

    g->view->show();
}

void MainWindow::on_plotCrackButton_clicked()
{
    //grab hashing and cracking algorithms

    switch(ui->hashComboBox->currentIndex()) {
    case 0:
        hashAlg = new Md5();
        break;
    case 1:
        hashAlg = new Sha512();
        break;
    case 2:
        hashAlg = new Pbkdf2();
        break;
    }

    Crack* c;
    if(hashAlg == NULL) {
        return;
    }

    switch(ui->crackComboBox->currentIndex()) {
    case 0:
        {int maxLength = ui->charCountSpinBox->text().toInt();
        c = new BruteForceCrack(hashAlg,bruteForceAlphabet(), maxLength);
        break;}

    case 1:
        {c = new DictionaryCrack(hashAlg, "../dictionary.txt");
        break;}
    }

    //generate data
    int beginChars = ui->charCountSpinBox_2->text().toInt();
    int count = ui->crackPointCountSpinBox->text().toInt();
    std::vector<std::string> strings = GenerateData::plaintexts(beginChars, count);
    std::vector<std::string> digests = GenerateData::getHashes(strings, hashAlg);
    crackDataPoints = GenerateData::crack(digests, c);

    //begin graphing
    g = new GraphWindow(ui->crackGraphicsView, crackDataPoints);
    g->vSize = 600;
    g->hSize = 600;

    if(ui->hashLogScaleCheckBox->isChecked()) {
        g->logScaleDraw();
    } else {
        g->draw();
    }
    g->addLabels("Milliseconds", "Number of characters");

    g->view->show();
}

void MainWindow::on_hashLogScaleCheckBox_clicked()
{
    if(g == NULL) {
        std::cout << "graphwindow object not initialized. No action to take." << std::endl;
        return;
    }
    if(crackDataPoints.size() == 0) {
        std::cout << "No points to graph." << std::endl;
        return;
    }

    g = new GraphWindow(ui->crackGraphicsView, crackDataPoints);
    g->vSize = 600;
    g->hSize = 600;

    if(ui->hashLogScaleCheckBox->isChecked()) {
        g->logScaleDraw();
    } else {
        g->draw();
    }
    g->addLabels("Milliseconds", "Number of characters");

    g->view->show();

}

void MainWindow::on_factorLogScaleCheckBox_clicked()
{
    if(g == NULL) {
        std::cout << "graphwindow object not initialized. No action to take." << std::endl;
        return;
    }
    if(factorDataPoints.size() == 0) {
        std::cout << "No points to graph." << std::endl;
        return;
    }

    g = new GraphWindow(ui->factoringGraphicsView, factorDataPoints);
    g->vSize = 600;
    g->hSize = 600;

    if(ui->factorLogScaleCheckBox->isChecked()) {
        g->logScaleDraw();
    } else {
        g->draw();
    }
    g->addLabels("Milliseconds", "Number of characters");

    g->view->show();
}
<|endoftext|>


<commit_before>#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cwchar>
#include <fstream>
#include <limits.h>

#include "Logger.h"

#include <Util/String/String.h>
#include <Util/System/System.h>

namespace Util {

namespace
{
    template <typename T>
    unsigned int increment(std::atomic<T> &value, const T &min, const T &max)
    {
        T currValue = 0, nextValue = 0;

        auto getNextValue = [&min, &max](const T &val)
        {
            return ((val < max - 1) ? val + 1 : min);
        };

        do
        {
            currValue = value.load();
            nextValue = getNextValue(currValue);
        } while (!value.compare_exchange_weak(currValue, nextValue));

        return currValue;
    }
}

//=============================================================================
LoggerWPtr Logger::s_wpInstance;
std::mutex Logger::s_consoleMutex;

//=============================================================================
Logger::Logger() :
    m_maxIndex((MAX_LOG_SIZE * 1024 * 1024) / sizeof(Log)),

    m_logBuffer(m_maxIndex),
    m_logIndex(0),

    m_flushingLog(false),

    m_maxDebugIndex(static_cast<const unsigned int>(m_maxIndex * 0.5)),
    m_maxInfoIndex(static_cast<const unsigned int>(m_maxIndex * 0.8)),
    m_maxWarningIndex(static_cast<const unsigned int>(m_maxIndex * 0.95)),
    m_maxErrorIndex(m_maxIndex),

    m_debugIndex(0),
    m_infoIndex(m_maxDebugIndex),
    m_warningIndex(m_maxInfoIndex),
    m_errorIndex(m_maxWarningIndex),

    m_startTime(std::chrono::high_resolution_clock::now())
{
}

//=============================================================================
Logger::~Logger()
{
    // TODO implement flush on desctruction option
}

//=============================================================================
void Logger::SetInstance(const LoggerPtr &spLogger)
{
    s_wpInstance = spLogger;
}

//=============================================================================
LoggerPtr Logger::GetInstance()
{
    return s_wpInstance.lock();
}

//=============================================================================
void Logger::ConsoleLog(const std::string &message)
{
    std::string timeStr = Util::System::LocalTime();

    std::lock_guard<std::mutex> lock(s_consoleMutex);
    std::cout << timeStr << ": " << message << std::endl;
}

//=============================================================================
void Logger::AddLog(LogLevel level, ssize_t gameId, const char *file,
    const char *func, unsigned int line, const std::string &message)
{
    LoggerPtr spLogger = GetInstance();

    if (spLogger)
    {
        spLogger->addLog(level, gameId, file, func, line, message);
    }
    else
    {
        std::string console = Util::String::Format("%d %d %s:%s:%d %s",
            level, gameId, file, func, line, message);

        ConsoleLog(console);
    }
}

//=============================================================================
void Logger::addLog(LogLevel level, ssize_t gameId, const char *file,
    const char *func, unsigned int line, const std::string &message)
{
    // Disallow logging while the log is being flushed
    // TODO come up with a better way to handle this case
    if (m_flushingLog.load())
    {
        return;
    }

    auto now = std::chrono::high_resolution_clock::now();
    auto logTime = std::chrono::duration_cast<std::chrono::duration<double>>(now - m_startTime);

    unsigned int index = 0;

    switch (level)
    {
    case LOG_DEBUG:
        index = increment(m_debugIndex, 0U, m_maxDebugIndex);
        break;

    case LOG_INFO:
        index = increment(m_infoIndex, m_maxDebugIndex, m_maxInfoIndex);
        break;

    case LOG_WARN:
        index = increment(m_warningIndex, m_maxInfoIndex, m_maxWarningIndex);
        break;

    case LOG_ERROR:
        index = increment(m_errorIndex, m_maxWarningIndex, m_maxErrorIndex);
        break;

    default:
        return;
    }

    Log *logToEdit = &m_logBuffer[index];

    logToEdit->m_index = m_logIndex.fetch_add(1);
    logToEdit->m_level = level;
    logToEdit->m_time = logTime.count();
    logToEdit->m_gameId = gameId;
    logToEdit->m_line = line;

    snprintf(logToEdit->m_file, sizeof(logToEdit->m_file), file);
    snprintf(logToEdit->m_function, sizeof(logToEdit->m_function), func);
    snprintf(logToEdit->m_message, sizeof(logToEdit->m_message), message.c_str());
}

//=============================================================================
void Logger::Flush()
{
    bool expected = false;

    // Only allow one thread to flush the log at a time
    if (!m_flushingLog.compare_exchange_strong(expected, true))
    {
        return;
    }

    // Move the contents of the log buffer to another vector
    std::vector<Log> logCopy;
    m_logBuffer.swap(logCopy);

    // Any thread can now try to add or flush logs
    m_flushingLog.store(false);

    // Sort based on log index
    auto compare = [](Log a, Log b) { return (a.m_index < b.m_index); };
    std::sort(logCopy.begin(), logCopy.end(), compare);

    std::string randStr = String::String::GenerateRandomString(10);
    std::string timeStr = Util::System::LocalTime();

    String::String::ReplaceAll(timeStr, ":", "-");
    String::String::ReplaceAll(timeStr, " ", "_");

    std::string fileName = "Log_" + timeStr + "_" + randStr + ".log";

    std::ofstream file;
    file.open(fileName.c_str(), std::ios::out);

    unsigned int ptr = 0;

    while ((logCopy[ptr].m_level < NUM_LEVELS) && (ptr < m_maxErrorIndex))
    {
        file << logCopy[ptr++];
    }

    file << std::flush;
}

}
<commit_msg>Fix compile warnings on Windows 10 bash (Also can't believe that's a sentence I just typed)<commit_after>#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cwchar>
#include <fstream>
#include <limits.h>

#include "Logger.h"

#include <Util/String/String.h>
#include <Util/System/System.h>

namespace Util {

namespace
{
    template <typename T>
    unsigned int increment(std::atomic<T> &value, const T &min, const T &max)
    {
        T currValue = 0, nextValue = 0;

        auto getNextValue = [&min, &max](const T &val)
        {
            return ((val < max - 1) ? val + 1 : min);
        };

        do
        {
            currValue = value.load();
            nextValue = getNextValue(currValue);
        } while (!value.compare_exchange_weak(currValue, nextValue));

        return currValue;
    }
}

//=============================================================================
LoggerWPtr Logger::s_wpInstance;
std::mutex Logger::s_consoleMutex;

//=============================================================================
Logger::Logger() :
    m_maxIndex((MAX_LOG_SIZE * 1024 * 1024) / sizeof(Log)),

    m_logBuffer(m_maxIndex),
    m_logIndex(0),

    m_flushingLog(false),

    m_maxDebugIndex(static_cast<const unsigned int>(m_maxIndex * 0.5)),
    m_maxInfoIndex(static_cast<const unsigned int>(m_maxIndex * 0.8)),
    m_maxWarningIndex(static_cast<const unsigned int>(m_maxIndex * 0.95)),
    m_maxErrorIndex(m_maxIndex),

    m_debugIndex(0),
    m_infoIndex(m_maxDebugIndex),
    m_warningIndex(m_maxInfoIndex),
    m_errorIndex(m_maxWarningIndex),

    m_startTime(std::chrono::high_resolution_clock::now())
{
}

//=============================================================================
Logger::~Logger()
{
    // TODO implement flush on desctruction option
}

//=============================================================================
void Logger::SetInstance(const LoggerPtr &spLogger)
{
    s_wpInstance = spLogger;
}

//=============================================================================
LoggerPtr Logger::GetInstance()
{
    return s_wpInstance.lock();
}

//=============================================================================
void Logger::ConsoleLog(const std::string &message)
{
    std::string timeStr = Util::System::LocalTime();

    std::lock_guard<std::mutex> lock(s_consoleMutex);
    std::cout << timeStr << ": " << message << std::endl;
}

//=============================================================================
void Logger::AddLog(LogLevel level, ssize_t gameId, const char *file,
    const char *func, unsigned int line, const std::string &message)
{
    LoggerPtr spLogger = GetInstance();

    if (spLogger)
    {
        spLogger->addLog(level, gameId, file, func, line, message);
    }
    else
    {
        std::string console = Util::String::Format("%d %d %s:%s:%d %s",
            level, gameId, file, func, line, message);

        ConsoleLog(console);
    }
}

//=============================================================================
void Logger::addLog(LogLevel level, ssize_t gameId, const char *file,
    const char *func, unsigned int line, const std::string &message)
{
    // Disallow logging while the log is being flushed
    // TODO come up with a better way to handle this case
    if (m_flushingLog.load())
    {
        return;
    }

    auto now = std::chrono::high_resolution_clock::now();
    auto logTime = std::chrono::duration_cast<std::chrono::duration<double>>(now - m_startTime);

    unsigned int index = 0;

    switch (level)
    {
    case LOG_DEBUG:
        index = increment(m_debugIndex, 0U, m_maxDebugIndex);
        break;

    case LOG_INFO:
        index = increment(m_infoIndex, m_maxDebugIndex, m_maxInfoIndex);
        break;

    case LOG_WARN:
        index = increment(m_warningIndex, m_maxInfoIndex, m_maxWarningIndex);
        break;

    case LOG_ERROR:
        index = increment(m_errorIndex, m_maxWarningIndex, m_maxErrorIndex);
        break;

    default:
        return;
    }

    Log *logToEdit = &m_logBuffer[index];

    logToEdit->m_index = m_logIndex.fetch_add(1);
    logToEdit->m_level = level;
    logToEdit->m_time = logTime.count();
    logToEdit->m_gameId = gameId;
    logToEdit->m_line = line;

    snprintf(logToEdit->m_file, sizeof(logToEdit->m_file), "%s", file);
    snprintf(logToEdit->m_function, sizeof(logToEdit->m_function), "%s", func);
    snprintf(logToEdit->m_message, sizeof(logToEdit->m_message), "%s", message.c_str());
}

//=============================================================================
void Logger::Flush()
{
    bool expected = false;

    // Only allow one thread to flush the log at a time
    if (!m_flushingLog.compare_exchange_strong(expected, true))
    {
        return;
    }

    // Move the contents of the log buffer to another vector
    std::vector<Log> logCopy;
    m_logBuffer.swap(logCopy);

    // Any thread can now try to add or flush logs
    m_flushingLog.store(false);

    // Sort based on log index
    auto compare = [](Log a, Log b) { return (a.m_index < b.m_index); };
    std::sort(logCopy.begin(), logCopy.end(), compare);

    std::string randStr = String::String::GenerateRandomString(10);
    std::string timeStr = Util::System::LocalTime();

    String::String::ReplaceAll(timeStr, ":", "-");
    String::String::ReplaceAll(timeStr, " ", "_");

    std::string fileName = "Log_" + timeStr + "_" + randStr + ".log";

    std::ofstream file;
    file.open(fileName.c_str(), std::ios::out);

    unsigned int ptr = 0;

    while ((logCopy[ptr].m_level < NUM_LEVELS) && (ptr < m_maxErrorIndex))
    {
        file << logCopy[ptr++];
    }

    file << std::flush;
}

}
<|endoftext|>


<commit_before>#include "carbon_user.h"
#include <stdio.h>
#include <stdlib.h>

int main()
{
   double frequency = 0;
   double voltage = 0;
   int rc;

   // invalid tile id
   rc = CarbonGetDVFS(-1, CORE, &frequency, &voltage);
   printf("test 1) Voltage: %g, Frequency: %g, RC: %i\n", voltage, frequency, rc);
   if (rc != -1){
      fprintf(stderr, "Expected RC = -1, got RC = %i", rc) ;
      exit(EXIT_FAILURE);
   }

   // invalid module type
   rc = CarbonGetDVFS(0, TILE, &frequency, &voltage);
   printf("test 2) Voltage: %g, Frequency: %g, RC: %i\n", voltage, frequency, rc);
   if (rc != -2){
      fprintf(stderr, "Expected RC = -2, got RC = %i", rc) ;
      exit(EXIT_FAILURE);
   }

   // invalid module type
   rc = CarbonSetDVFS(0, 0x2f, &frequency, AUTO);
   printf("test 3) Voltage: %g, Frequency: %g, RC: %i\n", voltage, frequency, rc);
   if (rc != -2){
      fprintf(stderr, "Expected RC = -2, got RC = %i", rc) ;
      exit(EXIT_FAILURE);
   }

   // invalid module type
   /*
   frequency = 1.0;
   rc = CarbonSetDVFS(0, L2_DIRECTORY, &frequency, AUTO);
   printf("test 4) Voltage: %g, Frequency: %g, RC: %i\n", voltage, frequency, rc);
   if (rc != -2){
      fprintf(stderr, "Expected RC = -2, got RC = %i", rc) ;
      exit(EXIT_FAILURE);
   }
*/

   // invalid voltage option
   rc = CarbonSetDVFS(0, TILE, &frequency, (voltage_option_t) 5);
   printf("test 5) Voltage: %g, Frequency: %g, RC: %i\n", voltage, frequency, rc);
   if (rc != -3){
      fprintf(stderr, "Expected RC = -3, got RC = %i", rc) ;
      exit(EXIT_FAILURE);
   }

   // invalid frequency
   frequency = 100;
   rc = CarbonSetDVFS(0, TILE, &frequency, AUTO);
   printf("test 6) Voltage: %g, Frequency: %g, RC: %i\n", voltage, frequency, rc);
   if (rc != -4){
      fprintf(stderr, "Expected RC = -4, got RC = %i", rc) ;
      exit(EXIT_FAILURE);
   }

   // above max frequency for current voltage
   frequency = 0.1;
   rc = CarbonSetDVFS(0, TILE, &frequency, AUTO);
   frequency = 2.0;
   rc = CarbonSetDVFS(0, TILE, &frequency, HOLD);
   printf("test 7) Voltage: %g, Frequency: %g, RC: %i\n", voltage, frequency, rc);
   if (rc != -5){
      fprintf(stderr, "Expected RC = -5, got RC = %i", rc) ;
      exit(EXIT_FAILURE);
   }

}
<commit_msg>[tests][dvfs] Corrected the dvfs unit test<commit_after>#include "carbon_user.h"
#include <stdio.h>
#include <stdlib.h>

int main()
{
   double frequency = 0;
   double voltage = 0;
   int rc;

   // invalid tile id
   rc = CarbonGetDVFS(-1, CORE, &frequency, &voltage);
   printf("test 1) Voltage: %g, Frequency: %g, RC: %i\n", voltage, frequency, rc);
   if (rc != -1){
      fprintf(stderr, "Expected RC = -1, got RC = %i", rc) ;
      exit(EXIT_FAILURE);
   }

   // invalid module type
   rc = CarbonGetDVFS(0, TILE, &frequency, &voltage);
   printf("test 2) Voltage: %g, Frequency: %g, RC: %i\n", voltage, frequency, rc);
   if (rc != -2){
      fprintf(stderr, "Expected RC = -2, got RC = %i", rc) ;
      exit(EXIT_FAILURE);
   }

   // invalid frequency
   rc = CarbonSetDVFS(0, 0x2f, &frequency, AUTO);
   printf("test 3) Voltage: %g, Frequency: %g, RC: %i\n", voltage, frequency, rc);
   if (rc != -4){
      fprintf(stderr, "Expected RC = -4, got RC = %i", rc) ;
      exit(EXIT_FAILURE);
   }

   // invalid module type (works only for pr_l1_sh_l2_msi model)
   // frequency = 1.0;
   // rc = CarbonSetDVFS(0, L2_DIRECTORY, &frequency, AUTO);
   // printf("test 4) Voltage: %g, Frequency: %g, RC: %i\n", voltage, frequency, rc);
   // if (rc != -2){
   //    fprintf(stderr, "Expected RC = -2, got RC = %i", rc) ;
   //    exit(EXIT_FAILURE);
   // }

   // invalid voltage option
   rc = CarbonSetDVFS(0, TILE, &frequency, (voltage_option_t) 5);
   printf("test 5) Voltage: %g, Frequency: %g, RC: %i\n", voltage, frequency, rc);
   if (rc != -3){
      fprintf(stderr, "Expected RC = -3, got RC = %i", rc) ;
      exit(EXIT_FAILURE);
   }

   // invalid frequency
   frequency = 100;
   rc = CarbonSetDVFS(0, TILE, &frequency, AUTO);
   printf("test 6) Voltage: %g, Frequency: %g, RC: %i\n", voltage, frequency, rc);
   if (rc != -4){
      fprintf(stderr, "Expected RC = -4, got RC = %i", rc) ;
      exit(EXIT_FAILURE);
   }

   // above max frequency for current voltage
   frequency = 0.1;
   rc = CarbonSetDVFS(0, TILE, &frequency, AUTO);
   frequency = 2.0;
   rc = CarbonSetDVFS(0, TILE, &frequency, HOLD);
   printf("test 7) Voltage: %g, Frequency: %g, RC: %i\n", voltage, frequency, rc);
   if (rc != -5){
      fprintf(stderr, "Expected RC = -5, got RC = %i", rc) ;
      exit(EXIT_FAILURE);
   }

}
<|endoftext|>


<commit_before>#include <QtCore/QString>
#include <QtCore/QStringList>

const char * some_char_pointer_indirection(const char *)
{
    return nullptr;
}

const char * some_char_pointer()
{
    return nullptr;
}

void test()
{
    QString s1;
    const char *cstring = "foo";
    s1.contains("string"); // Warning
    s1.contains(some_char_pointer()); // OK

    QString s2 = "string"; // Warning
    QString s3 = QStringLiteral("string"); // OK
    QString s4(some_char_pointer()); // OK

    s1 += "foo"; // Warning
    s1 += QStringLiteral("foo"); // OK
    s1 += QLatin1String("foo"); // OK

    QString s5 = QString::fromLatin1("BAR"); // Warning
    QString s6 = QString::fromUtf8("BAR"); // Warning
    QString s7 = QString::fromLatin1(some_char_pointer()); // OK
    QString s8 = QString::fromUtf8(some_char_pointer()); // OK
    QString s81 = QString::fromUtf8(some_char_pointer_indirection("foo")); // OK
    QString s123 = QString::fromLatin1(some_char_pointer_indirection("foo")); // OK

    QString s9 = QLatin1String("string"); // Warning
    s9 =  QLatin1String("string"); // Warning
    s9 =  QLatin1String(some_char_pointer_indirection("foo")); // OK
    QString s10 = true ? QLatin1String("string1") : QLatin1String("string2"); // Warning
    s10 = true ? QLatin1String("string1") :  QLatin1String("string2"); // Warning

    QString s11 = QString(QLatin1String("foo")); // Warning, TODO
    QStringList stringList;
    stringList << QString::fromLatin1("foo", 1); // OK
    QString s12 = QLatin1String(""); // OK, QString is optimized for the empty case
    QString s = QLatin1String(cstring + sizeof("foo")); // OK
    s = QString::fromLatin1("bar %1").arg(1); // Warning
    s = QString::fromLatin1(true ? "foo" : "foo2").arg(1); // Warning
    s += QString::fromLatin1(  // Warning: Multi-line, to test FIXIT
        "foo" );
    QString::fromLatin1(true ? cstring : "cstring"); // OK
    QString escaped = "\\\\"; // Warning, to test fixit
    QString s13 = QString("foo"); // Warning
    QString s14 = QString(""); // Warning
    QString s15 = ""; // Warning
}

struct A
{
    A() : member(QLatin1String("foo")) {} // Warning
    QString member;
};

struct A2
{
    A2() : member(QStringLiteral("foo")) {} // OK
    void  test(const QString &calendarType = QLatin1String("gregorian") ); // Warning
    QString member;
};

void test3()
{
    QString s;
    if (s == QString::fromLatin1("foo")) // Warning
        return;
    if (s == QString::fromLatin1("foo %1").arg(1)) // Warning
        return;
}

void test4(const QString &) {}

void test5()
{
    test4(QString::fromLatin1("foo")); // Warning
    QString s;
    s.contains(QString::fromLatin1("a")); // Warning
    s.compare(QStringLiteral("a"), QString::fromLatin1("a")); // Warning
}

#include <exception>
void exceptionTest() // Just to test a crash
{
    try {

    } catch (std::exception e) {

    }
}

<commit_msg>Remove TODO<commit_after>#include <QtCore/QString>
#include <QtCore/QStringList>

const char * some_char_pointer_indirection(const char *)
{
    return nullptr;
}

const char * some_char_pointer()
{
    return nullptr;
}

void test()
{
    QString s1;
    const char *cstring = "foo";
    s1.contains("string"); // Warning
    s1.contains(some_char_pointer()); // OK

    QString s2 = "string"; // Warning
    QString s3 = QStringLiteral("string"); // OK
    QString s4(some_char_pointer()); // OK

    s1 += "foo"; // Warning
    s1 += QStringLiteral("foo"); // OK
    s1 += QLatin1String("foo"); // OK

    QString s5 = QString::fromLatin1("BAR"); // Warning
    QString s6 = QString::fromUtf8("BAR"); // Warning
    QString s7 = QString::fromLatin1(some_char_pointer()); // OK
    QString s8 = QString::fromUtf8(some_char_pointer()); // OK
    QString s81 = QString::fromUtf8(some_char_pointer_indirection("foo")); // OK
    QString s123 = QString::fromLatin1(some_char_pointer_indirection("foo")); // OK

    QString s9 = QLatin1String("string"); // Warning
    s9 =  QLatin1String("string"); // Warning
    s9 =  QLatin1String(some_char_pointer_indirection("foo")); // OK
    QString s10 = true ? QLatin1String("string1") : QLatin1String("string2"); // Warning
    s10 = true ? QLatin1String("string1") :  QLatin1String("string2"); // Warning

    QString s11 = QString(QLatin1String("foo")); // Warning
    QStringList stringList;
    stringList << QString::fromLatin1("foo", 1); // OK
    QString s12 = QLatin1String(""); // OK, QString is optimized for the empty case
    QString s = QLatin1String(cstring + sizeof("foo")); // OK
    s = QString::fromLatin1("bar %1").arg(1); // Warning
    s = QString::fromLatin1(true ? "foo" : "foo2").arg(1); // Warning
    s += QString::fromLatin1(  // Warning: Multi-line, to test FIXIT
        "foo" );
    QString::fromLatin1(true ? cstring : "cstring"); // OK
    QString escaped = "\\\\"; // Warning, to test fixit
    QString s13 = QString("foo"); // Warning
    QString s14 = QString(""); // Warning
    QString s15 = ""; // Warning
}

struct A
{
    A() : member(QLatin1String("foo")) {} // Warning
    QString member;
};

struct A2
{
    A2() : member(QStringLiteral("foo")) {} // OK
    void  test(const QString &calendarType = QLatin1String("gregorian") ); // Warning
    QString member;
};

void test3()
{
    QString s;
    if (s == QString::fromLatin1("foo")) // Warning
        return;
    if (s == QString::fromLatin1("foo %1").arg(1)) // Warning
        return;
}

void test4(const QString &) {}

void test5()
{
    test4(QString::fromLatin1("foo")); // Warning
    QString s;
    s.contains(QString::fromLatin1("a")); // Warning
    s.compare(QStringLiteral("a"), QString::fromLatin1("a")); // Warning
}

#include <exception>
void exceptionTest() // Just to test a crash
{
    try {

    } catch (std::exception e) {

    }
}

<|endoftext|>


<commit_before>#ifndef ARPACA_ARPACA_HPP_
#define ARPACA_ARPACA_HPP_

#include <algorithm>
#include <stdexcept>
#include <vector>
#include <eigen3/Eigen/Core>

// ARPACK interface
extern "C" {

// Lanczos method (double precision)
void dsaupd_(int* ido, char* bmat, int* n, char* which, int* nev, double* tol,
             double* resid, int* ncv, double* v, int* ldv, int* iparam,
             int* ipntr, double* workd, double* workl, int* lworkl, int* info);

// Lanczos method (single precision)
void ssaupd_(int* ido, char* bmat, int* n, char* which, int* nev, float* tol,
             float* resid, int* ncv, float* v, int* ldv, int* iparam,
             int* ipntr, float* workd, float* workl, int* lworkl, int* info);

// Eigenvalue problem solver for result of dsaupd_
void dseupd_(int* rvec, char* howmny, int* select, double* d, double* z,
             int* ldz, double* sigma, char* bmat, int* n, char* which, int* nev,
             double* tol, double* resid, int* ncv, double* v, int* ldv,
             int* iparam, int* ipntr, double* workd, double* workl, int* lworkl,
             int* info);

// Eigenvalue problem solver for result of ssaupd_
void sseupd_(int* rvec, char* howmny, int* select, float* d, float* z, int* ldz,
             float* sigma, char* bmat, int* n, char* which, int* nev,
             float* tol, float* resid, int* ncv, float* v, int* ldv,
             int* iparam, int* ipntr, float* workd, float* workl, int* lworkl,
             int* info);

}  // extern "C"

namespace arpaca {

// Type of eigenvalue to solve.
// Arpaca::SymmetricEigenSolver computes part of eigenvalues and eigenvectors.
// EigenvalueType indicates which part is to be solved.
enum EigenvalueType {
  ALGEBRAIC_LARGEST,  // Largest as real numbers
  ALGEBRAIC_SMALLEST,  // Smallest as real numbers
  ALGEBRAIC_BOTH_END,  // Both end as real numbers
  MAGNITUDE_LARGEST,  // Largest as absolute values
  MAGNITUDE_SMALLEST,  // Smallest as absolute values
};

namespace detail {

inline const char* GetNameOfEigenvalueType(EigenvalueType type)
{
  switch (type) {
    case ALGEBRAIC_LARGEST: return "LA";
    case ALGEBRAIC_SMALLEST: return "SA";
    case ALGEBRAIC_BOTH_END: return "BE";
    case MAGNITUDE_LARGEST: return "LM";
    case MAGNITUDE_SMALLEST: return "SM";
  }
  throw std::invalid_argument("Invalid eigenvalue type");
}

inline void GetNameOfEigenvalueType(EigenvalueType type, char* to)
{
  const char* from = GetNameOfEigenvalueType(type);
  std::copy(from, from + 3, to);
}

template<typename Scalar>
void saupd(int* ido, char* bmat, int* n, char* which, int* nev, Scalar* tol,
           Scalar* resid, int* ncv, Scalar* v, int* ldv, int* iparam,
           int* ipntr, Scalar* workd, Scalar* workl, int* lworkl, int* info)
{
  dsaupd_(ido, bmat, n, which, nev, tol, resid, ncv, v, ldv, iparam, ipntr,
          workd, workl, lworkl, info);
}

template<>
inline void saupd<float>(int* ido, char* bmat, int* n, char* which, int* nev,
                         float* tol, float* resid, int* ncv, float* v, int* ldv,
                         int* iparam, int* ipntr, float* workd, float* workl,
                         int* lworkl, int* info)
{
  ssaupd_(ido, bmat, n, which, nev, tol, resid, ncv, v, ldv, iparam, ipntr,
          workd, workl, lworkl, info);
}

template<typename Scalar>
void seupd(int* rvec, char* howmny, int* select, Scalar* d, Scalar* z, int* ldz,
           Scalar* sigma, char* bmat, int* n, char* which, int* nev,
           Scalar* tol, Scalar* resid, int* ncv, Scalar* v, int* ldv,
           int* iparam, int* ipntr, Scalar* workd, Scalar* workl, int* lworkl,
           int* info)
{
  dseupd_(rvec, howmny, select, d, z, ldz, sigma, bmat, n, which, nev, tol,
          resid, ncv, v, ldv, iparam, ipntr, workd, workl, lworkl, info);
}

template<>
void seupd<float>(int* rvec, char* howmny, int* select, float* d, float* z,
                  int* ldz, float* sigma, char* bmat, int* n, char* which,
                  int* nev, float* tol, float* resid, int* ncv, float* v,
                  int* ldv, int* iparam, int* ipntr, float* workd, float* workl,
                  int* lworkl, int* info)
{
  sseupd_(rvec, howmny, select, d, z, ldz, sigma, bmat, n, which, nev, tol,
          resid, ncv, v, ldv, iparam, ipntr, workd, workl, lworkl, info);
}

}  // namespace detail

// Eigenvalue problem solver for symmetric matrix (especially sparse one).
// It partly computes eigenvalues and eigenvectors of a symmetric matrix A using
// ARPACK, which implements Implicitly Restarted Arnoldi (IRA) method.
template<typename Scalar = double>
class SymmetricEigenSolver {
 public:
  typedef Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> Matrix;
  typedef Eigen::Matrix<Scalar, Eigen::Dynamic, 1> Vector;

  SymmetricEigenSolver()
      : num_lanczos_vectors_(100),
        max_iterations_(100),
        tolerance_(-1)
  {
    SetEigenvalueType(MAGNITUDE_LARGEST);
  }

  // Sets # of Lanczos vectors.
  // From two to four times larger than # of objective eigenvalues is
  // recommended.
  //
  // NOTE: IRA approximates subspace containing the objective eigenvectors by
  // constructing |num| orthogonal basis vectors in each iteration, which is
  // improved for each iteration. Consequently, too small |num| causes slow
  // convergence, while too large |num| requires large size of memory and even
  // make each iteration too slow.
  void SetNumLanczosVectors(int num)
  {
    num_lanczos_vectors_ = num;
  }

  // Sets max # of Lanczos iterations.
  void SetMaxIterations(int num)
  {
    if (num <= 0)
      throw std::invalid_argument("Given # of iterations is not positive");
    max_iterations_ = num;
  }

  // Sets precision tolerance for computation.
  // Negative value means machine precision.
  void SetTolerance(Scalar tolerance)
  {
    tolerance_ = tolerance;
  }

  // Sets the type of eigenvalues to solve.
  // See EigenvalueType for detail.
  void SetEigenvalueType(EigenvalueType type)
  {
    detail::GetNameOfEigenvalueType(type, eigenvalue_type_name_);
  }

  // Solves the eigenvalue problem of a real symmetrix matrix A.
  // The matrix A is not set explicitly. Solve() only needs the operator
  // y = A * x.
  //
  // dimension:       Dimension of space (rows or cols of the matrix A).
  // num_eigenvalues: # of eigenvalues to compute.
  // op:              Functor that computes operation y = A * x. Signature is
  //                  op(x, y), where x and y are slices of Eigen::VectorX{d,f},
  //                  i.e. return values of Eigen::VectorX{d,f}::middleRows().
  template<typename OperatorATimes>
  void Solve(int dimension, int num_eigenvalues, OperatorATimes op)
  {
    if (dimension <= 0)
      throw std::invalid_argument("Given dimension is not positive");
    if (num_eigenvalues <= 0)
      throw std::invalid_argument("Given num_eigenvalues is not positive");

    // Eigenvalues (Lanczos)
    int info = 0;

    num_eigenvalues = std::max(std::min(num_eigenvalues, dimension), 0);

    int num_lanczos_vectors = num_lanczos_vectors_;
    if (num_lanczos_vectors <= 0)
      num_lanczos_vectors = num_eigenvalues * 3;
    else if (num_lanczos_vectors <= num_eigenvalues)
      num_lanczos_vectors = num_eigenvalues + 1;

    num_lanczos_vectors = std::min(num_lanczos_vectors, dimension);

    char bmat[2] = { 'I' };
    int leading_dimension = dimension;

    int iparam[11] = {}, ipntr[11] = {};
    iparam[0] = 1;  // Use effective shift
    iparam[2] = max_iterations_;
    iparam[3] = 1;  // block size
    iparam[6] = 1;  // Solve standard eigenvalue problem

    // Calculation workspace
    int lworkl = (num_lanczos_vectors + 8) * num_lanczos_vectors;
    Vector workd(3 * dimension), workl(lworkl);
    std::vector<Scalar> residue(dimension);
    Matrix lanczos_vectors(dimension, num_lanczos_vectors);

    // Lanczos iterations
    for (int mode = 0; mode != 99; ) {
      detail::saupd(&mode, bmat, &dimension, eigenvalue_type_name_,
                    &num_eigenvalues, &tolerance_, &residue[0],
                    &num_lanczos_vectors, lanczos_vectors.data(),
                    &leading_dimension, iparam, ipntr, workd.data(),
                    workl.data(), &lworkl, &info);

      switch (mode) {
        case -1:
          op(workd.middleRows(ipntr[0] - 1, dimension),
             workd.middleRows(ipntr[1] - 1, dimension));
          break;
        case 1:
          op(workd.middleRows(ipntr[2] - 1, dimension),
             workd.middleRows(ipntr[1] - 1, dimension));
          workd.middleRows(ipntr[2] - 1, dimension) =
              workd.middleRows(ipntr[0] - 1, dimension);
          break;
        case 2:
          workd.middleRows(ipntr[1] - 1, dimension) =
              workd.middleRows(ipntr[0] - 1, dimension);
          break;
      }
    }

    info_ = info;
    num_actual_iterations_ = iparam[2];
    num_converged_eigenvalues_ = iparam[4];

    // Eigenvectors
    int rvec = 1;  // Compute eigenvectors
    char howmany[2] = { 'A' };
    std::vector<int> select(num_lanczos_vectors);
    Scalar sigma;

    eigenvectors_.resize(dimension, num_eigenvalues);
    eigenvalues_.resize(num_eigenvalues);

    detail::seupd(&rvec, howmany, &select[0], eigenvalues_.data(),
                  eigenvectors_.data(), &dimension, &sigma, bmat, &dimension,
                  eigenvalue_type_name_, &num_eigenvalues, &tolerance_,
                  &residue[0], &num_lanczos_vectors, lanczos_vectors.data(),
                  &leading_dimension, iparam, ipntr, workd.data(), workl.data(),
                  &lworkl, &info);
  }

  // Gets the computed eigenvectors.
  // Returned matrix contains each eigenvector in each column.
  const Matrix& eigenvectors() const
  {
    return eigenvectors_;
  }

  // Gets the computed eigenvalues.
  const Vector& eigenvalues() const
  {
    return eigenvalues_;
  }

  Matrix MoveEigenvectors()
  {
    Matrix eigenvectors;
    eigenvectors.swap(eigenvectors_);
    return eigenvectors;
  }

  Vector MoveEigenvalues()
  {
    Vector eigenvalues;
    eigenvalues.swap(eigenvalues_);
    return eigenvalues;
  }

  int num_actual_iterations() const
  {
    return num_actual_iterations_;
  }

  int num_converged_eigenvalues() const
  {
    return num_converged_eigenvalues_;
  }

  // Gets information message based on error code of ARPACK.
  const char* GetInfo() const
  {
    switch (info_) {
      case 0: return "Normal exit";
      case 1: return "Not converged";
      case 3: return "num_lanczos_vectors may be too small";
      case -8: return "Error on tridiagonal eigenvalue calculation";
      case -9999: return "Could not build an Arnoldi factorization";
    }
    return "Arpaca internal error";
  }

 private:
  Matrix eigenvectors_;
  Vector eigenvalues_;

  int num_lanczos_vectors_;
  int max_iterations_;
  Scalar tolerance_;

  int info_;
  int num_actual_iterations_;
  int num_converged_eigenvalues_;

  char eigenvalue_type_name_[3];
};

// Default operator for the case the matrix A is explicitly given.
template<typename MatrixType>
class DefaultOperator {
 public:
  explicit DefaultOperator(MatrixType& m)
      : m_(m)
  {}

  template<typename X, typename Y>
  void operator()(X x, Y y) const
  {
    y = m_ * x;
  }

 private:
  MatrixType& m_;
};

template<typename Matrix>
inline DefaultOperator<Matrix> MakeDefaultOperator(Matrix& A)
{
  return DefaultOperator<Matrix>(A);
}

// Solves the eigenvalue problem of a real symmetrix matrix A, where the matrix
// A is explicitly given.
template<typename Matrix>
SymmetricEigenSolver<typename Matrix::Scalar> Solve(
    const Matrix& A,
    int num_eigenvalues,
    EigenvalueType type = MAGNITUDE_LARGEST,
    int num_lanczos_vectors = 0,
    int max_iterations = 10000,
    typename Matrix::Scalar tolerance = -1)
{
  SymmetricEigenSolver<typename Matrix::Scalar> solver;
  solver.SetEigenvalueType(type);
  solver.SetMaxIterations(max_iterations);
  solver.SetNumLanczosVectors(num_lanczos_vectors);
  solver.SetTolerance(tolerance);

  solver.Solve(A.rows(), num_eigenvalues, MakeDefaultOperator(A));

  return solver;
}

}  // namespace arpaca

#endif  // ARPACA_ARPACA_HPP_
<commit_msg>fix: specialization of seupd<float> was not inlined<commit_after>#ifndef ARPACA_ARPACA_HPP_
#define ARPACA_ARPACA_HPP_

#include <algorithm>
#include <stdexcept>
#include <vector>
#include <eigen3/Eigen/Core>

// ARPACK interface
extern "C" {

// Lanczos method (double precision)
void dsaupd_(int* ido, char* bmat, int* n, char* which, int* nev, double* tol,
             double* resid, int* ncv, double* v, int* ldv, int* iparam,
             int* ipntr, double* workd, double* workl, int* lworkl, int* info);

// Lanczos method (single precision)
void ssaupd_(int* ido, char* bmat, int* n, char* which, int* nev, float* tol,
             float* resid, int* ncv, float* v, int* ldv, int* iparam,
             int* ipntr, float* workd, float* workl, int* lworkl, int* info);

// Eigenvalue problem solver for result of dsaupd_
void dseupd_(int* rvec, char* howmny, int* select, double* d, double* z,
             int* ldz, double* sigma, char* bmat, int* n, char* which, int* nev,
             double* tol, double* resid, int* ncv, double* v, int* ldv,
             int* iparam, int* ipntr, double* workd, double* workl, int* lworkl,
             int* info);

// Eigenvalue problem solver for result of ssaupd_
void sseupd_(int* rvec, char* howmny, int* select, float* d, float* z, int* ldz,
             float* sigma, char* bmat, int* n, char* which, int* nev,
             float* tol, float* resid, int* ncv, float* v, int* ldv,
             int* iparam, int* ipntr, float* workd, float* workl, int* lworkl,
             int* info);

}  // extern "C"

namespace arpaca {

// Type of eigenvalue to solve.
// Arpaca::SymmetricEigenSolver computes part of eigenvalues and eigenvectors.
// EigenvalueType indicates which part is to be solved.
enum EigenvalueType {
  ALGEBRAIC_LARGEST,  // Largest as real numbers
  ALGEBRAIC_SMALLEST,  // Smallest as real numbers
  ALGEBRAIC_BOTH_END,  // Both end as real numbers
  MAGNITUDE_LARGEST,  // Largest as absolute values
  MAGNITUDE_SMALLEST,  // Smallest as absolute values
};

namespace detail {

inline const char* GetNameOfEigenvalueType(EigenvalueType type)
{
  switch (type) {
    case ALGEBRAIC_LARGEST: return "LA";
    case ALGEBRAIC_SMALLEST: return "SA";
    case ALGEBRAIC_BOTH_END: return "BE";
    case MAGNITUDE_LARGEST: return "LM";
    case MAGNITUDE_SMALLEST: return "SM";
  }
  throw std::invalid_argument("Invalid eigenvalue type");
}

inline void GetNameOfEigenvalueType(EigenvalueType type, char* to)
{
  const char* from = GetNameOfEigenvalueType(type);
  std::copy(from, from + 3, to);
}

template<typename Scalar>
void saupd(int* ido, char* bmat, int* n, char* which, int* nev, Scalar* tol,
           Scalar* resid, int* ncv, Scalar* v, int* ldv, int* iparam,
           int* ipntr, Scalar* workd, Scalar* workl, int* lworkl, int* info)
{
  dsaupd_(ido, bmat, n, which, nev, tol, resid, ncv, v, ldv, iparam, ipntr,
          workd, workl, lworkl, info);
}

template<>
inline void saupd<float>(int* ido, char* bmat, int* n, char* which, int* nev,
                         float* tol, float* resid, int* ncv, float* v, int* ldv,
                         int* iparam, int* ipntr, float* workd, float* workl,
                         int* lworkl, int* info)
{
  ssaupd_(ido, bmat, n, which, nev, tol, resid, ncv, v, ldv, iparam, ipntr,
          workd, workl, lworkl, info);
}

template<typename Scalar>
void seupd(int* rvec, char* howmny, int* select, Scalar* d, Scalar* z, int* ldz,
           Scalar* sigma, char* bmat, int* n, char* which, int* nev,
           Scalar* tol, Scalar* resid, int* ncv, Scalar* v, int* ldv,
           int* iparam, int* ipntr, Scalar* workd, Scalar* workl, int* lworkl,
           int* info)
{
  dseupd_(rvec, howmny, select, d, z, ldz, sigma, bmat, n, which, nev, tol,
          resid, ncv, v, ldv, iparam, ipntr, workd, workl, lworkl, info);
}

template<>
inline void seupd<float>(int* rvec, char* howmny, int* select, float* d,
                         float* z, int* ldz, float* sigma, char* bmat, int* n,
                         char* which, int* nev, float* tol, float* resid,
                         int* ncv, float* v, int* ldv, int* iparam, int* ipntr,
                         float* workd, float* workl, int* lworkl, int* info)
{
  sseupd_(rvec, howmny, select, d, z, ldz, sigma, bmat, n, which, nev, tol,
          resid, ncv, v, ldv, iparam, ipntr, workd, workl, lworkl, info);
}

}  // namespace detail

// Eigenvalue problem solver for symmetric matrix (especially sparse one).
// It partly computes eigenvalues and eigenvectors of a symmetric matrix A using
// ARPACK, which implements Implicitly Restarted Arnoldi (IRA) method.
template<typename Scalar = double>
class SymmetricEigenSolver {
 public:
  typedef Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> Matrix;
  typedef Eigen::Matrix<Scalar, Eigen::Dynamic, 1> Vector;

  SymmetricEigenSolver()
      : num_lanczos_vectors_(100),
        max_iterations_(100),
        tolerance_(-1)
  {
    SetEigenvalueType(MAGNITUDE_LARGEST);
  }

  // Sets # of Lanczos vectors.
  // From two to four times larger than # of objective eigenvalues is
  // recommended.
  //
  // NOTE: IRA approximates subspace containing the objective eigenvectors by
  // constructing |num| orthogonal basis vectors in each iteration, which is
  // improved for each iteration. Consequently, too small |num| causes slow
  // convergence, while too large |num| requires large size of memory and even
  // make each iteration too slow.
  void SetNumLanczosVectors(int num)
  {
    num_lanczos_vectors_ = num;
  }

  // Sets max # of Lanczos iterations.
  void SetMaxIterations(int num)
  {
    if (num <= 0)
      throw std::invalid_argument("Given # of iterations is not positive");
    max_iterations_ = num;
  }

  // Sets precision tolerance for computation.
  // Negative value means machine precision.
  void SetTolerance(Scalar tolerance)
  {
    tolerance_ = tolerance;
  }

  // Sets the type of eigenvalues to solve.
  // See EigenvalueType for detail.
  void SetEigenvalueType(EigenvalueType type)
  {
    detail::GetNameOfEigenvalueType(type, eigenvalue_type_name_);
  }

  // Solves the eigenvalue problem of a real symmetrix matrix A.
  // The matrix A is not set explicitly. Solve() only needs the operator
  // y = A * x.
  //
  // dimension:       Dimension of space (rows or cols of the matrix A).
  // num_eigenvalues: # of eigenvalues to compute.
  // op:              Functor that computes operation y = A * x. Signature is
  //                  op(x, y), where x and y are slices of Eigen::VectorX{d,f},
  //                  i.e. return values of Eigen::VectorX{d,f}::middleRows().
  template<typename OperatorATimes>
  void Solve(int dimension, int num_eigenvalues, OperatorATimes op)
  {
    if (dimension <= 0)
      throw std::invalid_argument("Given dimension is not positive");
    if (num_eigenvalues <= 0)
      throw std::invalid_argument("Given num_eigenvalues is not positive");

    // Eigenvalues (Lanczos)
    int info = 0;

    num_eigenvalues = std::max(std::min(num_eigenvalues, dimension), 0);

    int num_lanczos_vectors = num_lanczos_vectors_;
    if (num_lanczos_vectors <= 0)
      num_lanczos_vectors = num_eigenvalues * 3;
    else if (num_lanczos_vectors <= num_eigenvalues)
      num_lanczos_vectors = num_eigenvalues + 1;

    num_lanczos_vectors = std::min(num_lanczos_vectors, dimension);

    char bmat[2] = { 'I' };
    int leading_dimension = dimension;

    int iparam[11] = {}, ipntr[11] = {};
    iparam[0] = 1;  // Use effective shift
    iparam[2] = max_iterations_;
    iparam[3] = 1;  // block size
    iparam[6] = 1;  // Solve standard eigenvalue problem

    // Calculation workspace
    int lworkl = (num_lanczos_vectors + 8) * num_lanczos_vectors;
    Vector workd(3 * dimension), workl(lworkl);
    std::vector<Scalar> residue(dimension);
    Matrix lanczos_vectors(dimension, num_lanczos_vectors);

    // Lanczos iterations
    for (int mode = 0; mode != 99; ) {
      detail::saupd(&mode, bmat, &dimension, eigenvalue_type_name_,
                    &num_eigenvalues, &tolerance_, &residue[0],
                    &num_lanczos_vectors, lanczos_vectors.data(),
                    &leading_dimension, iparam, ipntr, workd.data(),
                    workl.data(), &lworkl, &info);

      switch (mode) {
        case -1:
          op(workd.middleRows(ipntr[0] - 1, dimension),
             workd.middleRows(ipntr[1] - 1, dimension));
          break;
        case 1:
          op(workd.middleRows(ipntr[2] - 1, dimension),
             workd.middleRows(ipntr[1] - 1, dimension));
          workd.middleRows(ipntr[2] - 1, dimension) =
              workd.middleRows(ipntr[0] - 1, dimension);
          break;
        case 2:
          workd.middleRows(ipntr[1] - 1, dimension) =
              workd.middleRows(ipntr[0] - 1, dimension);
          break;
      }
    }

    info_ = info;
    num_actual_iterations_ = iparam[2];
    num_converged_eigenvalues_ = iparam[4];

    // Eigenvectors
    int rvec = 1;  // Compute eigenvectors
    char howmany[2] = { 'A' };
    std::vector<int> select(num_lanczos_vectors);
    Scalar sigma;

    eigenvectors_.resize(dimension, num_eigenvalues);
    eigenvalues_.resize(num_eigenvalues);

    detail::seupd(&rvec, howmany, &select[0], eigenvalues_.data(),
                  eigenvectors_.data(), &dimension, &sigma, bmat, &dimension,
                  eigenvalue_type_name_, &num_eigenvalues, &tolerance_,
                  &residue[0], &num_lanczos_vectors, lanczos_vectors.data(),
                  &leading_dimension, iparam, ipntr, workd.data(), workl.data(),
                  &lworkl, &info);
  }

  // Gets the computed eigenvectors.
  // Returned matrix contains each eigenvector in each column.
  const Matrix& eigenvectors() const
  {
    return eigenvectors_;
  }

  // Gets the computed eigenvalues.
  const Vector& eigenvalues() const
  {
    return eigenvalues_;
  }

  Matrix MoveEigenvectors()
  {
    Matrix eigenvectors;
    eigenvectors.swap(eigenvectors_);
    return eigenvectors;
  }

  Vector MoveEigenvalues()
  {
    Vector eigenvalues;
    eigenvalues.swap(eigenvalues_);
    return eigenvalues;
  }

  int num_actual_iterations() const
  {
    return num_actual_iterations_;
  }

  int num_converged_eigenvalues() const
  {
    return num_converged_eigenvalues_;
  }

  // Gets information message based on error code of ARPACK.
  const char* GetInfo() const
  {
    switch (info_) {
      case 0: return "Normal exit";
      case 1: return "Not converged";
      case 3: return "num_lanczos_vectors may be too small";
      case -8: return "Error on tridiagonal eigenvalue calculation";
      case -9999: return "Could not build an Arnoldi factorization";
    }
    return "Arpaca internal error";
  }

 private:
  Matrix eigenvectors_;
  Vector eigenvalues_;

  int num_lanczos_vectors_;
  int max_iterations_;
  Scalar tolerance_;

  int info_;
  int num_actual_iterations_;
  int num_converged_eigenvalues_;

  char eigenvalue_type_name_[3];
};

// Default operator for the case the matrix A is explicitly given.
template<typename MatrixType>
class DefaultOperator {
 public:
  explicit DefaultOperator(MatrixType& m)
      : m_(m)
  {}

  template<typename X, typename Y>
  void operator()(X x, Y y) const
  {
    y = m_ * x;
  }

 private:
  MatrixType& m_;
};

template<typename Matrix>
inline DefaultOperator<Matrix> MakeDefaultOperator(Matrix& A)
{
  return DefaultOperator<Matrix>(A);
}

// Solves the eigenvalue problem of a real symmetrix matrix A, where the matrix
// A is explicitly given.
template<typename Matrix>
SymmetricEigenSolver<typename Matrix::Scalar> Solve(
    const Matrix& A,
    int num_eigenvalues,
    EigenvalueType type = MAGNITUDE_LARGEST,
    int num_lanczos_vectors = 0,
    int max_iterations = 10000,
    typename Matrix::Scalar tolerance = -1)
{
  SymmetricEigenSolver<typename Matrix::Scalar> solver;
  solver.SetEigenvalueType(type);
  solver.SetMaxIterations(max_iterations);
  solver.SetNumLanczosVectors(num_lanczos_vectors);
  solver.SetTolerance(tolerance);

  solver.Solve(A.rows(), num_eigenvalues, MakeDefaultOperator(A));

  return solver;
}

}  // namespace arpaca

#endif  // ARPACA_ARPACA_HPP_
<|endoftext|>


<commit_before>/*
 * Copyright © 2013 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */
#include <gtest/gtest.h>
#include "standalone_scaffolding.h"
#include "main/compiler.h"
#include "main/mtypes.h"
#include "main/macros.h"
#include "ralloc.h"
#include "ir.h"
#include "glsl_parser_extras.h"
#include "glsl_symbol_table.h"

class common_builtin : public ::testing::Test {
public:
   common_builtin(GLenum shader_type)
      : shader_type(shader_type)
   {
      /* empty */
   }

   virtual void SetUp();
   virtual void TearDown();

   void string_starts_with_prefix(const char *str, const char *prefix);
   void names_start_with_gl();
   void uniforms_and_system_values_dont_have_explicit_location();
   void constants_are_constant();
   void no_invalid_variable_modes();

   GLenum shader_type;
   struct _mesa_glsl_parse_state *state;
   struct gl_shader *shader;
   void *mem_ctx;
   gl_context ctx;
   exec_list ir;
};

void
common_builtin::SetUp()
{
   this->mem_ctx = ralloc_context(NULL);
   this->ir.make_empty();

   initialize_context_to_defaults(&this->ctx, API_OPENGL_COMPAT);

   this->shader = rzalloc(this->mem_ctx, gl_shader);
   this->shader->Type = this->shader_type;

   this->state =
      new(mem_ctx) _mesa_glsl_parse_state(&this->ctx, this->shader->Type,
                                          this->shader);

   _mesa_glsl_initialize_types(this->state);
   _mesa_glsl_initialize_variables(&this->ir, this->state);
}

void
common_builtin::TearDown()
{
   ralloc_free(this->mem_ctx);
   this->mem_ctx = NULL;
}

void
common_builtin::string_starts_with_prefix(const char *str, const char *prefix)
{
   const size_t len = strlen(prefix);
   char *const name_prefix = new char[len + 1];

   strncpy(name_prefix, str, len);
   name_prefix[len] = '\0';
   EXPECT_STREQ(prefix, name_prefix) << "Bad name " << str;

   delete [] name_prefix;
}

void
common_builtin::names_start_with_gl()
{
   foreach_list(node, &this->ir) {
      ir_variable *const var = ((ir_instruction *) node)->as_variable();

      string_starts_with_prefix(var->name, "gl_");
   }
}

void
common_builtin::uniforms_and_system_values_dont_have_explicit_location()
{
   foreach_list(node, &this->ir) {
      ir_variable *const var = ((ir_instruction *) node)->as_variable();

      if (var->mode != ir_var_uniform && var->mode != ir_var_system_value)
         continue;

      EXPECT_FALSE(var->explicit_location);
      EXPECT_EQ(-1, var->location);
   }
}

void
common_builtin::constants_are_constant()
{
   foreach_list(node, &this->ir) {
      ir_variable *const var = ((ir_instruction *) node)->as_variable();

      if (var->mode != ir_var_auto)
         continue;

      EXPECT_FALSE(var->explicit_location);
      EXPECT_EQ(-1, var->location);
      EXPECT_TRUE(var->read_only);
   }
}

void
common_builtin::no_invalid_variable_modes()
{
   foreach_list(node, &this->ir) {
      ir_variable *const var = ((ir_instruction *) node)->as_variable();

      switch (var->mode) {
      case ir_var_auto:
      case ir_var_uniform:
      case ir_var_shader_in:
      case ir_var_shader_out:
      case ir_var_system_value:
         break;

      default:
         ADD_FAILURE() << "Built-in variable " << var->name
                       << " has an invalid mode " << int(var->mode);
         break;
      }
   }
}

/************************************************************/

class vertex_builtin : public common_builtin {
public:
   vertex_builtin()
      : common_builtin(GL_VERTEX_SHADER)
   {
      /* empty */
   }
};

TEST_F(vertex_builtin, names_start_with_gl)
{
   common_builtin::names_start_with_gl();
}

TEST_F(vertex_builtin, inputs_have_explicit_location)
{
   foreach_list(node, &this->ir) {
      ir_variable *const var = ((ir_instruction *) node)->as_variable();

      if (var->mode != ir_var_shader_in)
         continue;

      EXPECT_TRUE(var->explicit_location);
      EXPECT_NE(-1, var->location);
      EXPECT_GT(VERT_ATTRIB_GENERIC0, var->location);
      EXPECT_EQ(0u, var->location_frac);
   }
}

TEST_F(vertex_builtin, outputs_have_explicit_location)
{
   foreach_list(node, &this->ir) {
      ir_variable *const var = ((ir_instruction *) node)->as_variable();

      if (var->mode != ir_var_shader_out)
         continue;

      EXPECT_TRUE(var->explicit_location);
      EXPECT_NE(-1, var->location);
      EXPECT_GT(VARYING_SLOT_VAR0, var->location);
      EXPECT_EQ(0u, var->location_frac);

      /* Several varyings only exist in the fragment shader.  Be sure that no
       * outputs with these locations exist.
       */
      EXPECT_NE(VARYING_SLOT_PNTC, var->location);
      EXPECT_NE(VARYING_SLOT_FACE, var->location);
      EXPECT_NE(VARYING_SLOT_PRIMITIVE_ID, var->location);
   }
}

TEST_F(vertex_builtin, uniforms_and_system_values_dont_have_explicit_location)
{
   common_builtin::uniforms_and_system_values_dont_have_explicit_location();
}

TEST_F(vertex_builtin, constants_are_constant)
{
   common_builtin::constants_are_constant();
}

TEST_F(vertex_builtin, no_invalid_variable_modes)
{
   common_builtin::no_invalid_variable_modes();
}

/********************************************************************/

class fragment_builtin : public common_builtin {
public:
   fragment_builtin()
      : common_builtin(GL_FRAGMENT_SHADER)
   {
      /* empty */
   }
};

TEST_F(fragment_builtin, names_start_with_gl)
{
   common_builtin::names_start_with_gl();
}

TEST_F(fragment_builtin, inputs_have_explicit_location)
{
   foreach_list(node, &this->ir) {
      ir_variable *const var = ((ir_instruction *) node)->as_variable();

      if (var->mode != ir_var_shader_in)
	 continue;

      EXPECT_TRUE(var->explicit_location);
      EXPECT_NE(-1, var->location);
      EXPECT_GT(VARYING_SLOT_VAR0, var->location);
      EXPECT_EQ(0u, var->location_frac);

      /* Several varyings only exist in the vertex / geometry shader.  Be sure
       * that no inputs with these locations exist.
       */
      EXPECT_TRUE(_mesa_varying_slot_in_fs((gl_varying_slot) var->location));
   }
}

TEST_F(fragment_builtin, outputs_have_explicit_location)
{
   foreach_list(node, &this->ir) {
      ir_variable *const var = ((ir_instruction *) node)->as_variable();

      if (var->mode != ir_var_shader_out)
	 continue;

      EXPECT_TRUE(var->explicit_location);
      EXPECT_NE(-1, var->location);

      /* gl_FragData[] has location FRAG_RESULT_DATA0.  Locations beyond that
       * are invalid.
       */
      EXPECT_GE(FRAG_RESULT_DATA0, var->location);

      EXPECT_EQ(0u, var->location_frac);
   }
}

TEST_F(fragment_builtin, uniforms_and_system_values_dont_have_explicit_location)
{
   common_builtin::uniforms_and_system_values_dont_have_explicit_location();
}

TEST_F(fragment_builtin, constants_are_constant)
{
   common_builtin::constants_are_constant();
}

TEST_F(fragment_builtin, no_invalid_variable_modes)
{
   common_builtin::no_invalid_variable_modes();
}
<commit_msg>glsl/tests: Verify geometry shader built-ins generated by _mesa_glsl_initialize_variables<commit_after>/*
 * Copyright © 2013 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */
#include <gtest/gtest.h>
#include "standalone_scaffolding.h"
#include "main/compiler.h"
#include "main/mtypes.h"
#include "main/macros.h"
#include "ralloc.h"
#include "ir.h"
#include "glsl_parser_extras.h"
#include "glsl_symbol_table.h"

class common_builtin : public ::testing::Test {
public:
   common_builtin(GLenum shader_type)
      : shader_type(shader_type)
   {
      /* empty */
   }

   virtual void SetUp();
   virtual void TearDown();

   void string_starts_with_prefix(const char *str, const char *prefix);
   void names_start_with_gl();
   void uniforms_and_system_values_dont_have_explicit_location();
   void constants_are_constant();
   void no_invalid_variable_modes();

   GLenum shader_type;
   struct _mesa_glsl_parse_state *state;
   struct gl_shader *shader;
   void *mem_ctx;
   gl_context ctx;
   exec_list ir;
};

void
common_builtin::SetUp()
{
   this->mem_ctx = ralloc_context(NULL);
   this->ir.make_empty();

   initialize_context_to_defaults(&this->ctx, API_OPENGL_COMPAT);

   this->shader = rzalloc(this->mem_ctx, gl_shader);
   this->shader->Type = this->shader_type;

   this->state =
      new(mem_ctx) _mesa_glsl_parse_state(&this->ctx, this->shader->Type,
                                          this->shader);

   _mesa_glsl_initialize_types(this->state);
   _mesa_glsl_initialize_variables(&this->ir, this->state);
}

void
common_builtin::TearDown()
{
   ralloc_free(this->mem_ctx);
   this->mem_ctx = NULL;
}

void
common_builtin::string_starts_with_prefix(const char *str, const char *prefix)
{
   const size_t len = strlen(prefix);
   char *const name_prefix = new char[len + 1];

   strncpy(name_prefix, str, len);
   name_prefix[len] = '\0';
   EXPECT_STREQ(prefix, name_prefix) << "Bad name " << str;

   delete [] name_prefix;
}

void
common_builtin::names_start_with_gl()
{
   foreach_list(node, &this->ir) {
      ir_variable *const var = ((ir_instruction *) node)->as_variable();

      string_starts_with_prefix(var->name, "gl_");
   }
}

void
common_builtin::uniforms_and_system_values_dont_have_explicit_location()
{
   foreach_list(node, &this->ir) {
      ir_variable *const var = ((ir_instruction *) node)->as_variable();

      if (var->mode != ir_var_uniform && var->mode != ir_var_system_value)
         continue;

      EXPECT_FALSE(var->explicit_location);
      EXPECT_EQ(-1, var->location);
   }
}

void
common_builtin::constants_are_constant()
{
   foreach_list(node, &this->ir) {
      ir_variable *const var = ((ir_instruction *) node)->as_variable();

      if (var->mode != ir_var_auto)
         continue;

      EXPECT_FALSE(var->explicit_location);
      EXPECT_EQ(-1, var->location);
      EXPECT_TRUE(var->read_only);
   }
}

void
common_builtin::no_invalid_variable_modes()
{
   foreach_list(node, &this->ir) {
      ir_variable *const var = ((ir_instruction *) node)->as_variable();

      switch (var->mode) {
      case ir_var_auto:
      case ir_var_uniform:
      case ir_var_shader_in:
      case ir_var_shader_out:
      case ir_var_system_value:
         break;

      default:
         ADD_FAILURE() << "Built-in variable " << var->name
                       << " has an invalid mode " << int(var->mode);
         break;
      }
   }
}

/************************************************************/

class vertex_builtin : public common_builtin {
public:
   vertex_builtin()
      : common_builtin(GL_VERTEX_SHADER)
   {
      /* empty */
   }
};

TEST_F(vertex_builtin, names_start_with_gl)
{
   common_builtin::names_start_with_gl();
}

TEST_F(vertex_builtin, inputs_have_explicit_location)
{
   foreach_list(node, &this->ir) {
      ir_variable *const var = ((ir_instruction *) node)->as_variable();

      if (var->mode != ir_var_shader_in)
         continue;

      EXPECT_TRUE(var->explicit_location);
      EXPECT_NE(-1, var->location);
      EXPECT_GT(VERT_ATTRIB_GENERIC0, var->location);
      EXPECT_EQ(0u, var->location_frac);
   }
}

TEST_F(vertex_builtin, outputs_have_explicit_location)
{
   foreach_list(node, &this->ir) {
      ir_variable *const var = ((ir_instruction *) node)->as_variable();

      if (var->mode != ir_var_shader_out)
         continue;

      EXPECT_TRUE(var->explicit_location);
      EXPECT_NE(-1, var->location);
      EXPECT_GT(VARYING_SLOT_VAR0, var->location);
      EXPECT_EQ(0u, var->location_frac);

      /* Several varyings only exist in the fragment shader.  Be sure that no
       * outputs with these locations exist.
       */
      EXPECT_NE(VARYING_SLOT_PNTC, var->location);
      EXPECT_NE(VARYING_SLOT_FACE, var->location);
      EXPECT_NE(VARYING_SLOT_PRIMITIVE_ID, var->location);
   }
}

TEST_F(vertex_builtin, uniforms_and_system_values_dont_have_explicit_location)
{
   common_builtin::uniforms_and_system_values_dont_have_explicit_location();
}

TEST_F(vertex_builtin, constants_are_constant)
{
   common_builtin::constants_are_constant();
}

TEST_F(vertex_builtin, no_invalid_variable_modes)
{
   common_builtin::no_invalid_variable_modes();
}

/********************************************************************/

class fragment_builtin : public common_builtin {
public:
   fragment_builtin()
      : common_builtin(GL_FRAGMENT_SHADER)
   {
      /* empty */
   }
};

TEST_F(fragment_builtin, names_start_with_gl)
{
   common_builtin::names_start_with_gl();
}

TEST_F(fragment_builtin, inputs_have_explicit_location)
{
   foreach_list(node, &this->ir) {
      ir_variable *const var = ((ir_instruction *) node)->as_variable();

      if (var->mode != ir_var_shader_in)
	 continue;

      EXPECT_TRUE(var->explicit_location);
      EXPECT_NE(-1, var->location);
      EXPECT_GT(VARYING_SLOT_VAR0, var->location);
      EXPECT_EQ(0u, var->location_frac);

      /* Several varyings only exist in the vertex / geometry shader.  Be sure
       * that no inputs with these locations exist.
       */
      EXPECT_TRUE(_mesa_varying_slot_in_fs((gl_varying_slot) var->location));
   }
}

TEST_F(fragment_builtin, outputs_have_explicit_location)
{
   foreach_list(node, &this->ir) {
      ir_variable *const var = ((ir_instruction *) node)->as_variable();

      if (var->mode != ir_var_shader_out)
	 continue;

      EXPECT_TRUE(var->explicit_location);
      EXPECT_NE(-1, var->location);

      /* gl_FragData[] has location FRAG_RESULT_DATA0.  Locations beyond that
       * are invalid.
       */
      EXPECT_GE(FRAG_RESULT_DATA0, var->location);

      EXPECT_EQ(0u, var->location_frac);
   }
}

TEST_F(fragment_builtin, uniforms_and_system_values_dont_have_explicit_location)
{
   common_builtin::uniforms_and_system_values_dont_have_explicit_location();
}

TEST_F(fragment_builtin, constants_are_constant)
{
   common_builtin::constants_are_constant();
}

TEST_F(fragment_builtin, no_invalid_variable_modes)
{
   common_builtin::no_invalid_variable_modes();
}

/********************************************************************/

class geometry_builtin : public common_builtin {
public:
   geometry_builtin()
      : common_builtin(GL_GEOMETRY_SHADER)
   {
      /* empty */
   }
};

TEST_F(geometry_builtin, names_start_with_gl)
{
   common_builtin::names_start_with_gl();
}

TEST_F(geometry_builtin, inputs_have_explicit_location)
{
   foreach_list(node, &this->ir) {
      ir_variable *const var = ((ir_instruction *) node)->as_variable();

      if (var->mode != ir_var_shader_in)
	 continue;

      if (var->is_interface_instance()) {
         EXPECT_STREQ("gl_in", var->name);
         EXPECT_FALSE(var->explicit_location);
         EXPECT_EQ(-1, var->location);

         ASSERT_TRUE(var->type->is_array());

         const glsl_type *const instance_type = var->type->fields.array;

         for (unsigned i = 0; i < instance_type->length; i++) {
            const glsl_struct_field *const input =
               &instance_type->fields.structure[i];

            string_starts_with_prefix(input->name, "gl_");
            EXPECT_NE(-1, input->location);
            EXPECT_GT(VARYING_SLOT_VAR0, input->location);

            /* Several varyings only exist in the fragment shader.  Be sure
             * that no inputs with these locations exist.
             */
            EXPECT_NE(VARYING_SLOT_PNTC, input->location);
            EXPECT_NE(VARYING_SLOT_FACE, input->location);
         }
      } else {
         EXPECT_TRUE(var->explicit_location);
         EXPECT_NE(-1, var->location);
         EXPECT_GT(VARYING_SLOT_VAR0, var->location);
         EXPECT_EQ(0u, var->location_frac);
      }

      /* Several varyings only exist in the fragment shader.  Be sure that no
       * inputs with these locations exist.
       */
      EXPECT_NE(VARYING_SLOT_PNTC, var->location);
      EXPECT_NE(VARYING_SLOT_FACE, var->location);
   }
}

TEST_F(geometry_builtin, outputs_have_explicit_location)
{
   foreach_list(node, &this->ir) {
      ir_variable *const var = ((ir_instruction *) node)->as_variable();

      if (var->mode != ir_var_shader_out)
	 continue;

      EXPECT_TRUE(var->explicit_location);
      EXPECT_NE(-1, var->location);
      EXPECT_GT(VARYING_SLOT_VAR0, var->location);
      EXPECT_EQ(0u, var->location_frac);

      /* Several varyings only exist in the fragment shader.  Be sure that no
       * outputs with these locations exist.
       */
      EXPECT_NE(VARYING_SLOT_PNTC, var->location);
      EXPECT_NE(VARYING_SLOT_FACE, var->location);
   }
}

TEST_F(geometry_builtin, uniforms_and_system_values_dont_have_explicit_location)
{
   common_builtin::uniforms_and_system_values_dont_have_explicit_location();
}

TEST_F(geometry_builtin, constants_are_constant)
{
   common_builtin::constants_are_constant();
}

TEST_F(geometry_builtin, no_invalid_variable_modes)
{
   common_builtin::no_invalid_variable_modes();
}
<|endoftext|>