<commit_before>#include "calculator.h"
#include "ui_calculator.h"
#include <QDebug>
#include <QSound>
// TODO: QDateTime - do czasu!!!
//-----------------------------------
Calculator::Calculator(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::Calculator)
{
    ui->setupUi(this);

    waitingForOperand = true;

    addClicked = false;
    subtractClicked = false;
    multiplyClicked = false;
    divideClicked = false;

    sumTemp = 0.0;
    factorTemp = 0.0;
}

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

void Calculator::on_button_0_clicked()
{
    QSound::play(":/new/sounds/metal_click_1.wav");

    if (ui->screen->text() == "0" && ui->button_0->text().toInt() == 0.0)
    {
        return;
    }

    if (waitingForOperand)
    {
        ui->screen->clear();
        waitingForOperand = false;
    }
    ui->screen->setText(ui->screen->text() + "0");

}

void Calculator::on_button_1_clicked()
{
    QSound::play(":/new/sounds/metal_click_1.wav");

    if (ui->screen->text() == "0" && ui->button_1->text().toInt() == 0.0)
        return;

    if (waitingForOperand)
    {
        ui->screen->clear();
        waitingForOperand = false;
    }
    ui->screen->setText(ui->screen->text() + "1");
}

void Calculator::on_button_2_clicked()
{
    QSound::play(":/new/sounds/metal_click_1.wav");

    if (ui->screen->text() == "0" && ui->button_2->text().toInt() == 0.0)
        return;

    if (waitingForOperand)
    {
        ui->screen->clear();
        waitingForOperand = false;
    }
    ui->screen->setText(ui->screen->text() + "2");
}

void Calculator::on_button_3_clicked()
{
    QSound::play(":/new/sounds/metal_click_1.wav");

    if (ui->screen->text() == "0" && ui->button_3->text().toInt() == 0.0)
        return;

    if (waitingForOperand)
    {
        ui->screen->clear();
        waitingForOperand = false;
    }
    ui->screen->setText(ui->screen->text() + "3");
}

void Calculator::on_button_4_clicked()
{
    QSound::play(":/new/sounds/metal_click_1.wav");

    if (ui->screen->text() == "0" && ui->button_4->text().toInt() == 0.0)
        return;

    if (waitingForOperand)
    {
        ui->screen->clear();
        waitingForOperand = false;
    }
    ui->screen->setText(ui->screen->text() + "4");
}

void Calculator::on_button_5_clicked()
{
    QSound::play(":/new/sounds/metal_click_1.wav");

    if (ui->screen->text() == "0" && ui->button_5->text().toInt() == 0.0)
        return;

    if (waitingForOperand)
    {
        ui->screen->clear();
        waitingForOperand = false;
    }
    ui->screen->setText(ui->screen->text() + "5");
}

void Calculator::on_button_6_clicked()
{
    QSound::play(":/new/sounds/metal_click_1.wav");

    if (ui->screen->text() == "0" && ui->button_6->text().toInt() == 0.0)
        return;

    if (waitingForOperand)
    {
        ui->screen->clear();
        waitingForOperand = false;
    }
    ui->screen->setText(ui->screen->text() + "6");
}

void Calculator::on_button_7_clicked()
{
    QSound::play(":/new/sounds/metal_click_1.wav");

    if (ui->screen->text() == "0" && ui->button_7->text().toInt() == 0.0)
        return;

    if (waitingForOperand)
    {
        ui->screen->clear();
        waitingForOperand = false;
    }
    ui->screen->setText(ui->screen->text() + "7");
}

void Calculator::on_button_8_clicked()
{
    QSound::play(":/new/sounds/metal_click_1.wav");

    if (ui->screen->text() == "0" && ui->button_8->text().toInt() == 0.0)
        return;

    if (waitingForOperand)
    {
        ui->screen->clear();
        waitingForOperand = false;
    }
    ui->screen->setText(ui->screen->text() + "8");
}

void Calculator::on_button_9_clicked()
{
    QSound::play(":/new/sounds/metal_click_1.wav");

    if (ui->screen->text() == "0" && ui->button_9->text().toInt() == 0.0)
        return;

    if (waitingForOperand)
    {
        ui->screen->clear();
        waitingForOperand = false;
    }
    ui->screen->setText(ui->screen->text() + "9");
}

void Calculator::on_buttonComma_clicked()
{
    if(!ui->screen->text().contains("."))
    {
        ui->screen->setText(ui->screen->text() + ".");
    }
    waitingForOperand = false;
}

void Calculator::on_buttonAdd_clicked()
{
    QSound::play(":/new/sounds/operations_sound.wav");

    double operand = ui->screen->text().toDouble();
    qDebug() << operand;

    if(addClicked)
    {
        if(true)
        {
            sumTemp += operand;
        }
        ui->screen->setText(QString::number(sumTemp));
    }
    else
    {
        sumTemp = operand;
    }

    addClicked = true;

    ui->screen_1->setText(ui->screen_1->text().append(QString::number(operand) + " + "));

    waitingForOperand = true;
}

void Calculator::on_buttonSubtract_clicked()
{
    QSound::play(":/new/sounds/operations_sound.wav");

    double operand = ui->screen->text().toDouble();
    qDebug() << operand;

    if(subtractClicked)
    {
        if(true)
        {
            factorTemp -= operand;
        }
        ui->screen->setText(QString::number(factorTemp));
    }
    else
    {
        factorTemp = operand;
    }

    subtractClicked = true;

    ui->screen_1->setText(ui->screen_1->text().append(QString::number(operand) + " - "));

    waitingForOperand = true;
}

void Calculator::on_buttonMultiply_clicked()
{
    QSound::play(":/new/sounds/operations_sound.wav");

    double operand = ui->screen->text().toDouble();
    qDebug() << operand;

    if(multiplyClicked)
    {
        if(true)
        {
            factorTemp *= operand;
        }
        ui->screen->setText(QString::number(factorTemp));
    }
    else
    {
        factorTemp = operand;
    }

    multiplyClicked = true;

    ui->screen_1->setText(ui->screen_1->text().append(QString::number(operand) + " * "));

    waitingForOperand = true;
}

void Calculator::on_buttonShare_clicked()
{
    QSound::play(":/new/sounds/operations_sound.wav");

    double operand = ui->screen->text().toDouble();
    qDebug() << operand;

    if(divideClicked)
    {
        if(true)
        {
            factorTemp /= operand;
        }
        ui->screen->setText(QString::number(factorTemp));
    }
    else
    {
        factorTemp = operand;
    }

    divideClicked = true;

    ui->screen_1->setText(ui->screen_1->text().append(QString::number(operand) + " / "));

    waitingForOperand = true;
}

void Calculator::on_buttonEqual_clicked()
{
    QString text = ui->screen_1->text();
    double operand = ui->screen->text().toDouble();

    if(text.remove(0,(text.length()-3)) == " + ")
    {
        sumTemp += operand;
        ui->screen->setText(QString::number(sumTemp));
        ui->screen_1->clear();
    }
    if(text.remove(0,(text.length()-3)) == " - ")
    {
        sumTemp -= operand;
        ui->screen->setText(QString::number(sumTemp));
        ui->screen_1->clear();
    }
    if(text.remove(0,(text.length()-3)) == " * ")
    {
        factorTemp *= operand;
        ui->screen->setText(QString::number(factorTemp));
        ui->screen_1->clear();
    }
    if(text.remove(0,(text.length()-3)) == " / ")
    {
        if (operand == 0.0)
        {
            ui->screen->setText("Nie można dzielić przez 0");
            return;
        }
        factorTemp /= operand;
        ui->screen->setText(QString::number(factorTemp));
        ui->screen_1->clear();
    }
    sumTemp = 0.0;
    factorTemp = 0.0;

    addClicked = false;
    subtractClicked = false;
    multiplyClicked = false;
    divideClicked = false;

    waitingForOperand = true;
}

void Calculator::on_buttonReplace_clicked()
{
    QString text = ui->screen->text();
    double value = text.toDouble();

    if(value > 0.0)
    {
        text.prepend(tr("-"));
    }
    else if (value < 0.0)
    {
        text.remove(0,1);
    }
    //else if(value == 0.0)
    //{
    //    text.clear();
    //}

    ui->screen->setText(text);
}

//FIXME: sprawdzic jeszcze raz dla np. 0.345 itd, zmień if na switch-case
void Calculator::on_backSpace_clicked()
{
    QSound::play(":/new/sounds/backspace_sound.wav");

    QString text = ui->screen->text();

    if (text.indexOf("-",0) == true || text.length() <= 2)
    {
        if (text.toDouble() > 0.0)
        {
            ui->screen->backspace();
        }
        else
        {
            ui->screen->setText("0");
            waitingForOperand = true;
        }
        //text.clear();
    }
    else if( text.length() > 2 )
    {
        ui->screen->backspace();
    }
}

void Calculator::on_reset_clicked()
{
    QSound::play(":/new/sounds/delete.wav");

    ui->screen->clear();
    ui->screen_1->clear();
    ui->screen->setText("0");

    sumTemp = 0.0;
    factorTemp = 0.0;

    addClicked = false;
    subtractClicked = false;
    multiplyClicked = false;
    divideClicked = false;

    waitingForOperand = true;
}

void Calculator::on_back_clicked()
{
    if (waitingForOperand)
    {
        if(ui->screen->text() == "0")
        {
            return;
        }
        else
        {
            ui->screen->setText("0");
        }
    }
    else
    {
        ui->screen->setText("0");
        waitingForOperand = true;
    }
}
<commit_msg>update subtract<commit_after>#include "calculator.h"
#include "ui_calculator.h"
#include <QDebug>
#include <QSound>
// TODO: QDateTime - do czasu!!!
//-----------------------------------
Calculator::Calculator(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::Calculator)
{
    ui->setupUi(this);

    waitingForOperand = true;

    addClicked = false;
    subtractClicked = false;
    multiplyClicked = false;
    divideClicked = false;

    sumTemp = 0.0;
    factorTemp = 0.0;
}

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

void Calculator::on_button_0_clicked()
{
    QSound::play(":/new/sounds/metal_click_1.wav");

    if (ui->screen->text() == "0" && ui->button_0->text().toInt() == 0.0)
    {
        return;
    }

    if (waitingForOperand)
    {
        ui->screen->clear();
        waitingForOperand = false;
    }
    ui->screen->setText(ui->screen->text() + "0");

}

void Calculator::on_button_1_clicked()
{
    QSound::play(":/new/sounds/metal_click_1.wav");

    if (ui->screen->text() == "0" && ui->button_1->text().toInt() == 0.0)
        return;

    if (waitingForOperand)
    {
        ui->screen->clear();
        waitingForOperand = false;
    }
    ui->screen->setText(ui->screen->text() + "1");
}

void Calculator::on_button_2_clicked()
{
    QSound::play(":/new/sounds/metal_click_1.wav");

    if (ui->screen->text() == "0" && ui->button_2->text().toInt() == 0.0)
        return;

    if (waitingForOperand)
    {
        ui->screen->clear();
        waitingForOperand = false;
    }
    ui->screen->setText(ui->screen->text() + "2");
}

void Calculator::on_button_3_clicked()
{
    QSound::play(":/new/sounds/metal_click_1.wav");

    if (ui->screen->text() == "0" && ui->button_3->text().toInt() == 0.0)
        return;

    if (waitingForOperand)
    {
        ui->screen->clear();
        waitingForOperand = false;
    }
    ui->screen->setText(ui->screen->text() + "3");
}

void Calculator::on_button_4_clicked()
{
    QSound::play(":/new/sounds/metal_click_1.wav");

    if (ui->screen->text() == "0" && ui->button_4->text().toInt() == 0.0)
        return;

    if (waitingForOperand)
    {
        ui->screen->clear();
        waitingForOperand = false;
    }
    ui->screen->setText(ui->screen->text() + "4");
}

void Calculator::on_button_5_clicked()
{
    QSound::play(":/new/sounds/metal_click_1.wav");

    if (ui->screen->text() == "0" && ui->button_5->text().toInt() == 0.0)
        return;

    if (waitingForOperand)
    {
        ui->screen->clear();
        waitingForOperand = false;
    }
    ui->screen->setText(ui->screen->text() + "5");
}

void Calculator::on_button_6_clicked()
{
    QSound::play(":/new/sounds/metal_click_1.wav");

    if (ui->screen->text() == "0" && ui->button_6->text().toInt() == 0.0)
        return;

    if (waitingForOperand)
    {
        ui->screen->clear();
        waitingForOperand = false;
    }
    ui->screen->setText(ui->screen->text() + "6");
}

void Calculator::on_button_7_clicked()
{
    QSound::play(":/new/sounds/metal_click_1.wav");

    if (ui->screen->text() == "0" && ui->button_7->text().toInt() == 0.0)
        return;

    if (waitingForOperand)
    {
        ui->screen->clear();
        waitingForOperand = false;
    }
    ui->screen->setText(ui->screen->text() + "7");
}

void Calculator::on_button_8_clicked()
{
    QSound::play(":/new/sounds/metal_click_1.wav");

    if (ui->screen->text() == "0" && ui->button_8->text().toInt() == 0.0)
        return;

    if (waitingForOperand)
    {
        ui->screen->clear();
        waitingForOperand = false;
    }
    ui->screen->setText(ui->screen->text() + "8");
}

void Calculator::on_button_9_clicked()
{
    QSound::play(":/new/sounds/metal_click_1.wav");

    if (ui->screen->text() == "0" && ui->button_9->text().toInt() == 0.0)
        return;

    if (waitingForOperand)
    {
        ui->screen->clear();
        waitingForOperand = false;
    }
    ui->screen->setText(ui->screen->text() + "9");
}

void Calculator::on_buttonComma_clicked()
{
    if(!ui->screen->text().contains("."))
    {
        ui->screen->setText(ui->screen->text() + ".");
    }
    waitingForOperand = false;
}

void Calculator::on_buttonAdd_clicked()
{
    QSound::play(":/new/sounds/operations_sound.wav");

    double operand = ui->screen->text().toDouble();
    qDebug() << operand;

    if(addClicked)
    {
        if(true)
        {
            sumTemp += operand;
        }
        ui->screen->setText(QString::number(sumTemp));
    }
    else
    {
        sumTemp = operand;
    }

    addClicked = true;

    ui->screen_1->setText(ui->screen_1->text().append(QString::number(operand) + " + "));

    waitingForOperand = true;
}

void Calculator::on_buttonSubtract_clicked()
{
    QSound::play(":/new/sounds/operations_sound.wav");

    double operand = ui->screen->text().toDouble();
    qDebug() << operand;

    if(subtractClicked)
    {
        if(true)
        {
            sumTemp -= operand;
        }
        ui->screen->setText(QString::number(sumTemp));
    }
    else
    {
        sumTemp = operand;
    }

    subtractClicked = true;

    ui->screen_1->setText(ui->screen_1->text().append(QString::number(operand) + " - "));

    waitingForOperand = true;
}

void Calculator::on_buttonMultiply_clicked()
{
    QSound::play(":/new/sounds/operations_sound.wav");

    double operand = ui->screen->text().toDouble();
    qDebug() << operand;

    if(multiplyClicked)
    {
        if(true)
        {
            factorTemp *= operand;
        }
        ui->screen->setText(QString::number(factorTemp));
    }
    else
    {
        factorTemp = operand;
    }

    multiplyClicked = true;

    ui->screen_1->setText(ui->screen_1->text().append(QString::number(operand) + " * "));

    waitingForOperand = true;
}

void Calculator::on_buttonShare_clicked()
{
    QSound::play(":/new/sounds/operations_sound.wav");

    double operand = ui->screen->text().toDouble();
    qDebug() << operand;

    if(divideClicked)
    {
        if(true)
        {
            factorTemp /= operand;
        }
        ui->screen->setText(QString::number(factorTemp));
    }
    else
    {
        factorTemp = operand;
    }

    divideClicked = true;

    ui->screen_1->setText(ui->screen_1->text().append(QString::number(operand) + " / "));

    waitingForOperand = true;
}

void Calculator::on_buttonEqual_clicked()
{
    QString text = ui->screen_1->text();
    double operand = ui->screen->text().toDouble();

    if(text.remove(0,(text.length()-3)) == " + ")
    {
        sumTemp += operand;
        ui->screen->setText(QString::number(sumTemp));
        ui->screen_1->clear();
    }
    if(text.remove(0,(text.length()-3)) == " - ")
    {
        sumTemp -= operand;
        ui->screen->setText(QString::number(sumTemp));
        ui->screen_1->clear();
    }
    if(text.remove(0,(text.length()-3)) == " * ")
    {
        factorTemp *= operand;
        ui->screen->setText(QString::number(factorTemp));
        ui->screen_1->clear();
    }
    if(text.remove(0,(text.length()-3)) == " / ")
    {
        if (operand == 0.0)
        {
            ui->screen->setText("Nie można dzielić przez 0");
            return;
        }
        factorTemp /= operand;
        ui->screen->setText(QString::number(factorTemp));
        ui->screen_1->clear();
    }
    sumTemp = 0.0;
    factorTemp = 0.0;

    addClicked = false;
    subtractClicked = false;
    multiplyClicked = false;
    divideClicked = false;

    waitingForOperand = true;
}

void Calculator::on_buttonReplace_clicked()
{
    QString text = ui->screen->text();
    double value = text.toDouble();

    if(value > 0.0)
    {
        text.prepend(tr("-"));
    }
    else if (value < 0.0)
    {
        text.remove(0,1);
    }
    //else if(value == 0.0)
    //{
    //    text.clear();
    //}

    ui->screen->setText(text);
}

//FIXME: sprawdzic jeszcze raz dla np. 0.345 itd, zmień if na switch-case
void Calculator::on_backSpace_clicked()
{
    QSound::play(":/new/sounds/backspace_sound.wav");

    QString text = ui->screen->text();

    if (text.indexOf("-",0) == true || text.length() <= 2)
    {
        if (text.toDouble() > 0.0)
        {
            ui->screen->backspace();
        }
        else
        {
            ui->screen->setText("0");
            waitingForOperand = true;
        }
        //text.clear();
    }
    else if( text.length() > 2 )
    {
        ui->screen->backspace();
    }
}

void Calculator::on_reset_clicked()
{
    QSound::play(":/new/sounds/delete.wav");

    ui->screen->clear();
    ui->screen_1->clear();
    ui->screen->setText("0");

    sumTemp = 0.0;
    factorTemp = 0.0;

    addClicked = false;
    subtractClicked = false;
    multiplyClicked = false;
    divideClicked = false;

    waitingForOperand = true;
}

void Calculator::on_back_clicked()
{
    if (waitingForOperand)
    {
        if(ui->screen->text() == "0")
        {
            return;
        }
        else
        {
            ui->screen->setText("0");
        }
    }
    else
    {
        ui->screen->setText("0");
        waitingForOperand = true;
    }
}
<|endoftext|>


<commit_before>/*
 * gVirtuS -- A GPGPU transparent virtualization component.
 *
 * Copyright (C) 2009-2011  The University of Napoli Parthenope at Naples.
 *
 * This file is part of gVirtuS.
 *
 * gVirtuS is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * gVirtuS is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with gVirtuS; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Written by: Giuseppe Coviello <giuseppe.coviello@uniparthenope.it>,
 *             Department of Applied Science
 */

#include <cufft.h>

#include "Frontend.h"

#include <iostream>

using namespace std;

extern "C" cufftResult cufftPlan1d(cufftHandle *plan, int nx, cufftType type,
        int batch) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(nx);
    in->Add(type);
    in->Add(batch);
    f->Execute("cufftPlan1d");
    *plan = (cufftHandle) f->GetOutputBuffer()->Get<uint64_t>();
    return (cufftResult) f->GetExitCode();
}

extern "C" cufftResult cufftPlan2d(cufftHandle *plan, int nx, int ny,
        cufftType type) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(nx);
    in->Add(ny);
    in->Add(type);
    f->Execute("cufftPlan2d");
    *plan = f->GetOutputBuffer()->Get<cufftHandle>();
    return (cufftResult) f->GetExitCode();
}

extern "C" cufftResult cufftPlan3d(cufftHandle *plan, int nx, int ny, int nz,
        cufftType type) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(nx);
    in->Add(ny);
    in->Add(nz);
    in->Add(type);
    f->Execute("cufftPlan3d");
    *plan = (cufftHandle) f->GetOutputBuffer()->Get<uint64_t>();
    return (cufftResult) f->GetExitCode();
}

extern "C" cufftResult cufftPlanMany(cufftHandle *plan, int rank, int *n,
        int *inembed, int istride, int idist, int *onembed, int ostride,
        int odist, cufftType type, int batch) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(rank);
    in->Add(*n);
    in->Add(istride);
    in->Add(idist);
    in->Add(ostride);
    in->Add(odist);
    in->Add(type);
    in->Add(batch);
    f->Execute("cufftPlanMany");
    *plan = (cufftHandle) f->GetOutputBuffer()->Get<uint64_t>();
    *n = f->GetOutputBuffer()->Get<int>();
    return (cufftResult) f->GetExitCode();
}

extern "C" cufftResult cufftDestroy(cufftHandle plan) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(plan);
    f->Execute("cufftDestroy");
    return (cufftResult) f->GetExitCode();
}

extern "C" cufftResult cufftExecC2C(cufftHandle plan, cufftComplex *idata,
        cufftComplex *odata, int direction) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(plan);
    in->Add(idata);
    in->Add(odata);
    in->Add(direction);
    f->Execute("cufftExecC2C");
    return (cufftResult) f->GetExitCode();
}

extern "C" cufftResult cufftExecR2C(cufftHandle plan, cufftReal *idata,
        cufftComplex *odata) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(plan);
    in->Add(idata);
    in->Add(odata);
    f->Execute("cufftExecR2C");
    return (cufftResult) f->GetExitCode();
}

extern "C" cufftResult cufftExecC2R(cufftHandle plan, cufftComplex *idata,
        cufftReal *odata) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(plan);
    in->Add((uint64_t) idata);
    in->Add((uint64_t) odata);
    f->Execute("cufftExecC2R");
    return (cufftResult) f->GetExitCode();
}

extern "C" cufftResult cufftExecZ2Z(cufftHandle plan, cufftDoubleComplex *idata,
        cufftDoubleComplex *odata, int direction) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(plan);
    in->Add(idata);
    in->Add(odata);
    in->Add(direction);
    f->Execute("cufftExecZ2z");
    return (cufftResult) f->GetExitCode();
}

extern "C" cufftResult cufftExecD2Z(cufftHandle plan, cufftDoubleReal *idata,
        cufftDoubleComplex *odata) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(plan);
    in->Add(idata);
    in->Add(odata);
    f->Execute("cufftExecD2Z");
    return (cufftResult) f->GetExitCode();
}

extern "C" cufftResult cufftExecZ2D(cufftHandle plan, cufftDoubleComplex *idata,
        cufftDoubleReal *odata) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(plan);
    in->Add(idata);
    in->Add(odata);
    f->Execute("cufftExecZ2D");
    return (cufftResult) f->GetExitCode();

}

extern "C" cufftResult cufftSetStream(cufftHandle plan, cudaStream_t stream) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(plan);
    in->Add((uint64_t) stream);
    f->Execute("cufftSetStream");
    return (cufftResult) f->GetExitCode();
}

extern "C" cufftResult cufftSetCompatibilityMode(cufftHandle plan,
        cufftCompatibility mode){
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(plan);
    in->Add(mode);
    f->Execute("cufftSetCompatibilityMode");
    return (cufftResult) f->GetExitCode();
}<commit_msg>The frontend have to be updated<commit_after>/*
 * gVirtuS -- A GPGPU transparent virtualization component.
 *
 * Copyright (C) 2009-2011  The University of Napoli Parthenope at Naples.
 *
 * This file is part of gVirtuS.
 *
 * gVirtuS is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * gVirtuS is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with gVirtuS; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Written by: Giuseppe Coviello <giuseppe.coviello@uniparthenope.it>,
 *             Department of Applied Science
 */

#include <cufft.h>

#include "Frontend.h"

#include <iostream>

using namespace std;

extern "C" cufftResult cufftPlan1d(cufftHandle *plan, int nx, cufftType type,
        int batch) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(nx);
    in->Add(type);
    in->Add(batch);
    f->Execute("cufftPlan1d");
    cout << hex << f->GetOutputBuffer() << endl;
    cout << hex << f->GetOutputBuffer()->Get<uint64_t>();
    *plan = (cufftHandle) f->GetOutputBuffer()->Get<uint64_t>();
    cout << "CCCC\n";
    return (cufftResult) f->GetExitCode();
}

extern "C" cufftResult cufftPlan2d(cufftHandle *plan, int nx, int ny,
        cufftType type) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(nx);
    in->Add(ny);
    in->Add(type);
    f->Execute("cufftPlan2d");
    *plan = f->GetOutputBuffer()->Get<cufftHandle>();
    return (cufftResult) f->GetExitCode();
}

extern "C" cufftResult cufftPlan3d(cufftHandle *plan, int nx, int ny, int nz,
        cufftType type) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(nx);
    in->Add(ny);
    in->Add(nz);
    in->Add(type);
    f->Execute("cufftPlan3d");
    *plan = (cufftHandle) f->GetOutputBuffer()->Get<uint64_t>();
    return (cufftResult) f->GetExitCode();
}

extern "C" cufftResult cufftPlanMany(cufftHandle *plan, int rank, int *n,
        int *inembed, int istride, int idist, int *onembed, int ostride,
        int odist, cufftType type, int batch) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(rank);
    in->Add(*n);
    in->Add(istride);
    in->Add(idist);
    in->Add(ostride);
    in->Add(odist);
    in->Add(type);
    in->Add(batch);
    f->Execute("cufftPlanMany");
    *plan = (cufftHandle) f->GetOutputBuffer()->Get<uint64_t>();
    *n = f->GetOutputBuffer()->Get<int>();
    return (cufftResult) f->GetExitCode();
}

extern "C" cufftResult cufftDestroy(cufftHandle plan) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(plan);
    f->Execute("cufftDestroy");
    return (cufftResult) f->GetExitCode();
}

extern "C" cufftResult cufftExecC2C(cufftHandle plan, cufftComplex *idata,
        cufftComplex *odata, int direction) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(plan);
    in->Add(idata);
    in->Add(odata);
    in->Add(direction);
    f->Execute("cufftExecC2C");
    return (cufftResult) f->GetExitCode();
}

extern "C" cufftResult cufftExecR2C(cufftHandle plan, cufftReal *idata,
        cufftComplex *odata) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(plan);
    in->Add(idata);
    in->Add(odata);
    f->Execute("cufftExecR2C");
    return (cufftResult) f->GetExitCode();
}

extern "C" cufftResult cufftExecC2R(cufftHandle plan, cufftComplex *idata,
        cufftReal *odata) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(plan);
    in->Add((uint64_t) idata);
    in->Add((uint64_t) odata);
    f->Execute("cufftExecC2R");
    return (cufftResult) f->GetExitCode();
}

extern "C" cufftResult cufftExecZ2Z(cufftHandle plan, cufftDoubleComplex *idata,
        cufftDoubleComplex *odata, int direction) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(plan);
    in->Add(idata);
    in->Add(odata);
    in->Add(direction);
    f->Execute("cufftExecZ2z");
    return (cufftResult) f->GetExitCode();
}

extern "C" cufftResult cufftExecD2Z(cufftHandle plan, cufftDoubleReal *idata,
        cufftDoubleComplex *odata) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(plan);
    in->Add(idata);
    in->Add(odata);
    f->Execute("cufftExecD2Z");
    return (cufftResult) f->GetExitCode();
}

extern "C" cufftResult cufftExecZ2D(cufftHandle plan, cufftDoubleComplex *idata,
        cufftDoubleReal *odata) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(plan);
    in->Add(idata);
    in->Add(odata);
    f->Execute("cufftExecZ2D");
    return (cufftResult) f->GetExitCode();

}

extern "C" cufftResult cufftSetStream(cufftHandle plan, cudaStream_t stream) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(plan);
    in->Add((uint64_t) stream);
    f->Execute("cufftSetStream");
    return (cufftResult) f->GetExitCode();
}

extern "C" cufftResult cufftSetCompatibilityMode(cufftHandle plan,
        cufftCompatibility mode){
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(plan);
    in->Add(mode);
    f->Execute("cufftSetCompatibilityMode");
    return (cufftResult) f->GetExitCode();
}
<|endoftext|>


<commit_before><commit_msg>layers: Verify that src of copy update is updated<commit_after><|endoftext|>


<commit_before><commit_msg>[Driver] Write the all-sources file even under -save-temps.<commit_after><|endoftext|>


<commit_before><commit_msg>Wrap to 80 columns, no functionality change.<commit_after><|endoftext|>


<commit_before>// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <string.h>
#include <limits>

#include "include/v8stdint.h"
#include "src/ostreams.h"
#include "test/cctest/cctest.h"

using namespace v8::internal;

TEST(OStringStreamConstructor) {
  OStringStream oss;
  CHECK_EQ(0, oss.size());
  CHECK_GT(oss.capacity(), 0);
  CHECK_NE(NULL, oss.data());
  CHECK_EQ("", oss.c_str());
}

#define TEST_STRING            \
  "Ash nazg durbatuluk, "      \
  "ash nazg gimbatul, "        \
  "ash nazg thrakatuluk, "     \
  "agh burzum-ishi krimpatul."

TEST(OStringStreamGrow) {
  OStringStream oss;
  const int repeat = 30;
  size_t len = strlen(TEST_STRING);
  for (int i = 0; i < repeat; ++i) {
    oss.write(TEST_STRING, len);
  }
  const char* expected =
      TEST_STRING TEST_STRING TEST_STRING TEST_STRING TEST_STRING
      TEST_STRING TEST_STRING TEST_STRING TEST_STRING TEST_STRING
      TEST_STRING TEST_STRING TEST_STRING TEST_STRING TEST_STRING
      TEST_STRING TEST_STRING TEST_STRING TEST_STRING TEST_STRING
      TEST_STRING TEST_STRING TEST_STRING TEST_STRING TEST_STRING
      TEST_STRING TEST_STRING TEST_STRING TEST_STRING TEST_STRING;
  const size_t expected_len = len * repeat;
  CHECK_EQ(static_cast<int>(expected_len), oss.size());
  CHECK_GT(oss.capacity(), 0);
  CHECK_EQ(0, strncmp(expected, oss.data(), expected_len));
  CHECK_EQ(expected, oss.c_str());
}

template <class T>
static void check(const char* expected, T value) {
  OStringStream oss;
  oss << value << " " << hex << value;
  CHECK_EQ(expected, oss.c_str());
}

TEST(NumericFormatting) {
  check<bool>("0 0", false);
  check<bool>("1 1", true);

  check<int16_t>("-12345 cfc7", -12345);
  check<int16_t>("-32768 8000", std::numeric_limits<int16_t>::min());
  check<int16_t>("32767 7fff", std::numeric_limits<int16_t>::max());

  check<uint16_t>("34567 8707", 34567);
  check<uint16_t>("0 0", std::numeric_limits<uint16_t>::min());
  check<uint16_t>("65535 ffff", std::numeric_limits<uint16_t>::max());

  check<int32_t>("-1234567 ffed2979", -1234567);
  check<int32_t>("-2147483648 80000000", std::numeric_limits<int32_t>::min());
  check<int32_t>("2147483647 7fffffff", std::numeric_limits<int32_t>::max());

  check<uint32_t>("3456789 34bf15", 3456789);
  check<uint32_t>("0 0", std::numeric_limits<uint32_t>::min());
  check<uint32_t>("4294967295 ffffffff", std::numeric_limits<uint32_t>::max());

  check<int64_t>("-1234567 ffffffffffed2979", -1234567);
  check<int64_t>("-9223372036854775808 8000000000000000",
                 std::numeric_limits<int64_t>::min());
  check<int64_t>("9223372036854775807 7fffffffffffffff",
                 std::numeric_limits<int64_t>::max());

  check<uint64_t>("3456789 34bf15", 3456789);
  check<uint64_t>("0 0", std::numeric_limits<uint64_t>::min());
  check<uint64_t>("18446744073709551615 ffffffffffffffff",
                  std::numeric_limits<uint64_t>::max());

  check<float>("0 0", 0.0f);
  check<float>("123 123", 123.0f);
  check<float>("-0.5 -0.5", -0.5f);
  check<float>("1.25 1.25", 1.25f);
  check<float>("0.0625 0.0625", 6.25e-2f);

  check<double>("0 0", 0.0);
  check<double>("123 123", 123.0);
  check<double>("-0.5 -0.5", -0.5);
  check<double>("1.25 1.25", 1.25);
  check<double>("0.0625 0.0625", 6.25e-2);
}

TEST(CharacterOutput) {
  check<char>("a a", 'a');
  check<signed char>("B B", 'B');
  check<unsigned char>("9 9", '9');
  check<const char*>("bye bye", "bye");

  OStringStream os;
  os.put('H').write("ello", 4);
  CHECK_EQ("Hello", os.c_str());
}

TEST(Manipulators) {
  OStringStream os;
  os << 123 << hex << 123 << endl << 123 << dec << 123 << 123;
  CHECK_EQ("1237b\n7b123123", os.c_str());
}

class MiscStuff {
 public:
  MiscStuff(int i, double d, const char* s) : i_(i), d_(d), s_(s) { }

 private:
  friend OStream& operator<<(OStream& os, const MiscStuff& m);

  int i_;
  double d_;
  const char* s_;
};

OStream& operator<<(OStream& os, const MiscStuff& m) {
  return os << "{i:" << m.i_ << ", d:" << m.d_ << ", s:'" << m.s_ << "'}";
}

TEST(CustomOutput) {
  OStringStream os;
  MiscStuff m(123, 4.5, "Hurz!");
  os << m;
  CHECK_EQ("{i:123, d:4.5, s:'Hurz!'}", os.c_str());
}
<commit_msg>Unbreak Win64 build (hopefully).<commit_after>// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <string.h>
#include <limits>

#include "include/v8stdint.h"
#include "src/ostreams.h"
#include "test/cctest/cctest.h"

using namespace v8::internal;

TEST(OStringStreamConstructor) {
  OStringStream oss;
  const size_t expected_size = 0;
  CHECK(expected_size == oss.size());
  CHECK_GT(oss.capacity(), 0);
  CHECK_NE(NULL, oss.data());
  CHECK_EQ("", oss.c_str());
}

#define TEST_STRING            \
  "Ash nazg durbatuluk, "      \
  "ash nazg gimbatul, "        \
  "ash nazg thrakatuluk, "     \
  "agh burzum-ishi krimpatul."

TEST(OStringStreamGrow) {
  OStringStream oss;
  const int repeat = 30;
  size_t len = strlen(TEST_STRING);
  for (int i = 0; i < repeat; ++i) {
    oss.write(TEST_STRING, len);
  }
  const char* expected =
      TEST_STRING TEST_STRING TEST_STRING TEST_STRING TEST_STRING
      TEST_STRING TEST_STRING TEST_STRING TEST_STRING TEST_STRING
      TEST_STRING TEST_STRING TEST_STRING TEST_STRING TEST_STRING
      TEST_STRING TEST_STRING TEST_STRING TEST_STRING TEST_STRING
      TEST_STRING TEST_STRING TEST_STRING TEST_STRING TEST_STRING
      TEST_STRING TEST_STRING TEST_STRING TEST_STRING TEST_STRING;
  const size_t expected_len = len * repeat;
  CHECK(expected_len == oss.size());
  CHECK_GT(oss.capacity(), 0);
  CHECK_EQ(0, strncmp(expected, oss.data(), expected_len));
  CHECK_EQ(expected, oss.c_str());
}

template <class T>
static void check(const char* expected, T value) {
  OStringStream oss;
  oss << value << " " << hex << value;
  CHECK_EQ(expected, oss.c_str());
}

TEST(NumericFormatting) {
  check<bool>("0 0", false);
  check<bool>("1 1", true);

  check<int16_t>("-12345 cfc7", -12345);
  check<int16_t>("-32768 8000", std::numeric_limits<int16_t>::min());
  check<int16_t>("32767 7fff", std::numeric_limits<int16_t>::max());

  check<uint16_t>("34567 8707", 34567);
  check<uint16_t>("0 0", std::numeric_limits<uint16_t>::min());
  check<uint16_t>("65535 ffff", std::numeric_limits<uint16_t>::max());

  check<int32_t>("-1234567 ffed2979", -1234567);
  check<int32_t>("-2147483648 80000000", std::numeric_limits<int32_t>::min());
  check<int32_t>("2147483647 7fffffff", std::numeric_limits<int32_t>::max());

  check<uint32_t>("3456789 34bf15", 3456789);
  check<uint32_t>("0 0", std::numeric_limits<uint32_t>::min());
  check<uint32_t>("4294967295 ffffffff", std::numeric_limits<uint32_t>::max());

  check<int64_t>("-1234567 ffffffffffed2979", -1234567);
  check<int64_t>("-9223372036854775808 8000000000000000",
                 std::numeric_limits<int64_t>::min());
  check<int64_t>("9223372036854775807 7fffffffffffffff",
                 std::numeric_limits<int64_t>::max());

  check<uint64_t>("3456789 34bf15", 3456789);
  check<uint64_t>("0 0", std::numeric_limits<uint64_t>::min());
  check<uint64_t>("18446744073709551615 ffffffffffffffff",
                  std::numeric_limits<uint64_t>::max());

  check<float>("0 0", 0.0f);
  check<float>("123 123", 123.0f);
  check<float>("-0.5 -0.5", -0.5f);
  check<float>("1.25 1.25", 1.25f);
  check<float>("0.0625 0.0625", 6.25e-2f);

  check<double>("0 0", 0.0);
  check<double>("123 123", 123.0);
  check<double>("-0.5 -0.5", -0.5);
  check<double>("1.25 1.25", 1.25);
  check<double>("0.0625 0.0625", 6.25e-2);
}

TEST(CharacterOutput) {
  check<char>("a a", 'a');
  check<signed char>("B B", 'B');
  check<unsigned char>("9 9", '9');
  check<const char*>("bye bye", "bye");

  OStringStream os;
  os.put('H').write("ello", 4);
  CHECK_EQ("Hello", os.c_str());
}

TEST(Manipulators) {
  OStringStream os;
  os << 123 << hex << 123 << endl << 123 << dec << 123 << 123;
  CHECK_EQ("1237b\n7b123123", os.c_str());
}

class MiscStuff {
 public:
  MiscStuff(int i, double d, const char* s) : i_(i), d_(d), s_(s) { }

 private:
  friend OStream& operator<<(OStream& os, const MiscStuff& m);

  int i_;
  double d_;
  const char* s_;
};

OStream& operator<<(OStream& os, const MiscStuff& m) {
  return os << "{i:" << m.i_ << ", d:" << m.d_ << ", s:'" << m.s_ << "'}";
}

TEST(CustomOutput) {
  OStringStream os;
  MiscStuff m(123, 4.5, "Hurz!");
  os << m;
  CHECK_EQ("{i:123, d:4.5, s:'Hurz!'}", os.c_str());
}
<|endoftext|>


<commit_before>#include "aten.h"
#include "atenscene.h"

#include <cmdline.h>
#include <imgui.h>

#include "VoxelViewer.h"

static const int WIDTH = 1280;
static const int HEIGHT = 720;

static const char* TITLE = "VoxelViewer";

struct Options {
	std::string input;
	std::string output;

	std::string inputBasepath;
	std::string inputFilename;
} g_opt;

static std::vector<aten::object*> g_objs;
static aten::AcceleratedScene<aten::sbvh> g_scene;

static VoxelViewer g_viewer;
static aten::RasterizeRenderer g_rasterizer;

static aten::PinholeCamera g_camera;
static bool g_isCameraDirty = false;

static bool g_willShowGUI = true;

static int g_drawVoxelDepth = 1;
static bool g_drawMesh = false;
static bool g_isWireframe = false;

static bool g_isMouseLBtnDown = false;
static bool g_isMouseRBtnDown = false;
static int g_prevX = 0;
static int g_prevY = 0;

static std::vector<std::vector<aten::ThreadedSbvhNode>> g_voxels;

void onRun(aten::window* window)
{
	if (g_isCameraDirty) {
		g_camera.update();

		auto camparam = g_camera.param();
		camparam.znear = real(0.1);
		camparam.zfar = real(10000.0);

		g_isCameraDirty = false;
	}

	// TODO
	auto sbvh = (aten::sbvh*)g_objs[0]->getInternalAccelerator();

	if (g_voxels.empty()) {
		auto maxDepth = sbvh->getMaxDepth();
		g_voxels.resize(maxDepth);

		// NOTE
		// nodes[0] is top layer.
		const auto& nodes = g_scene.getAccel()->getNodes();
		g_viewer.bringVoxels(nodes[1], g_voxels);
	}

	g_viewer.draw(
		&g_camera,
		g_voxels,
		g_isWireframe,
		g_drawVoxelDepth);

	if (g_drawMesh) {
		for (auto obj : g_objs) {
			g_rasterizer.draw(obj, &g_camera, false);
		}
	}

	{
		ImGui::SliderInt("Depth", &g_drawVoxelDepth, 1, sbvh->getMaxDepth());
		ImGui::Checkbox("Wireframe,", &g_isWireframe);
		ImGui::Checkbox("Draw mesh,", &g_drawMesh);

		window->drawImGui();
	}
}

void onClose()
{

}

void onMouseBtn(bool left, bool press, int x, int y)
{
	g_isMouseLBtnDown = false;
	g_isMouseRBtnDown = false;

	if (press) {
		g_prevX = x;
		g_prevY = y;

		g_isMouseLBtnDown = left;
		g_isMouseRBtnDown = !left;
	}
}

void onMouseMove(int x, int y)
{
	if (g_isMouseLBtnDown) {
		aten::CameraOperator::rotate(
			g_camera,
			WIDTH, HEIGHT,
			g_prevX, g_prevY,
			x, y);
		g_isCameraDirty = true;
	}
	else if (g_isMouseRBtnDown) {
		aten::CameraOperator::move(
			g_camera,
			g_prevX, g_prevY,
			x, y,
			real(0.001));
		g_isCameraDirty = true;
	}

	g_prevX = x;
	g_prevY = y;
}

void onMouseWheel(int delta)
{
	aten::CameraOperator::dolly(g_camera, delta * real(0.1));
	g_isCameraDirty = true;
}

void onKey(bool press, aten::Key key)
{
	static const real offset = real(0.1);

	if (press) {
		if (key == aten::Key::Key_F1) {
			g_willShowGUI = !g_willShowGUI;
			return;
		}
	}

	if (press) {
		switch (key) {
		case aten::Key::Key_W:
		case aten::Key::Key_UP:
			aten::CameraOperator::moveForward(g_camera, offset);
			break;
		case aten::Key::Key_S:
		case aten::Key::Key_DOWN:
			aten::CameraOperator::moveForward(g_camera, -offset);
			break;
		case aten::Key::Key_D:
		case aten::Key::Key_RIGHT:
			aten::CameraOperator::moveRight(g_camera, offset);
			break;
		case aten::Key::Key_A:
		case aten::Key::Key_LEFT:
			aten::CameraOperator::moveRight(g_camera, -offset);
			break;
		case aten::Key::Key_Z:
			aten::CameraOperator::moveUp(g_camera, offset);
			break;
		case aten::Key::Key_X:
			aten::CameraOperator::moveUp(g_camera, -offset);
			break;
		default:
			break;
		}

		g_isCameraDirty = true;
	}
}

bool parseOption(
	int argc, char* argv[],
	cmdline::parser& cmd,
	Options& opt)
{
	{
		cmd.add<std::string>("input", 'i', "input filename", true);
		cmd.add<std::string>("output", 'o', "output filename base", false, "result");

		cmd.add<std::string>("help", '?', "print usage", false);
	}

	bool isCmdOk = cmd.parse(argc, argv);

	if (cmd.exist("help")) {
		std::cerr << cmd.usage();
		return false;
	}

	if (!isCmdOk) {
		std::cerr << cmd.error() << std::endl << cmd.usage();
		return false;
	}

	if (cmd.exist("input")) {
		opt.input = cmd.get<std::string>("input");
	}
	else {
		std::cerr << cmd.error() << std::endl << cmd.usage();
		return false;
	}

	if (cmd.exist("output")) {
		opt.output = cmd.get<std::string>("output");
	}
	else {
		// TODO
		opt.output = "result.sbvh";
	}

	return true;
}

// TODO
void loadObj(const Options& opt)
{
#if 0
	auto emit = new aten::emissive(aten::vec3(36, 33, 24));
	aten::AssetManager::registerMtrl(
		"light",
		emit);

	aten::ObjLoader::load(g_objs, opt.input);
#elif 1
	aten::ObjLoader::load(g_objs, opt.input);
#else
	aten::ObjLoader::load(g_objs, "../../asset/sponza/sponza.obj");

	g_objs[0]->importInternalAccelTree("../../asset/sponza/sponza.sbvh");
#endif

	for (auto obj : g_objs) {
		auto instance = new aten::instance<aten::object>(obj, aten::mat4::Identity);
		g_scene.add(instance);
	}

	g_scene.build();
}

int main(int argc, char* argv[])
{
	//g_opt.input = "../../asset/cornellbox/orig.obj";
	//g_opt.input = "../../asset/sponza/lod.obj";
	//g_opt.input = "../../asset/suzanne/suzanne.obj";
	g_opt.input = "../../asset/bunny/bunny.obj";

	// TODO
#if 0
	cmdline::parser cmd;

	if (!parseOption(argc, argv, cmd, g_opt)) {
		return 0;
	}
#endif

	std::string extname;
	aten::getStringsFromPath(g_opt.input, g_opt.inputBasepath, extname, g_opt.inputFilename);

	aten::SetCurrentDirectoryFromExe();

	aten::AssetManager::suppressWarnings();

	aten::window::init(
		WIDTH, HEIGHT,
		TITLE,
		onRun,
		onClose,
		onMouseBtn,
		onMouseMove,
		onMouseWheel,
		onKey);

	loadObj(g_opt);

	aten::texture::initAllAsGLTexture();

	// TODO
	aten::vec3 pos(0, 1, 3);
	aten::vec3 at(0, 1, 0);
	real vfov = real(45);

	g_camera.init(
		pos,
		at,
		aten::vec3(0, 1, 0),
		vfov,
		WIDTH, HEIGHT);

	g_viewer.init(
		WIDTH, HEIGHT,
		"voxelviewer_vs.glsl",
		"voxelviewer_fs.glsl");

	g_rasterizer.init(
		WIDTH, HEIGHT,
		"../shader/drawobj_vs.glsl",
		"../shader/drawobj_fs.glsl");

	aten::window::run();

	aten::window::terminate();

	return 1;
}
<commit_msg>Modify to read and register a material.<commit_after>#include "aten.h"
#include "atenscene.h"

#include <cmdline.h>
#include <imgui.h>

#include "VoxelViewer.h"

static const int WIDTH = 1280;
static const int HEIGHT = 720;

static const char* TITLE = "VoxelViewer";

struct Options {
	std::string input;
	std::string output;

	std::string inputBasepath;
	std::string inputFilename;
} g_opt;

static std::vector<aten::object*> g_objs;
static aten::AcceleratedScene<aten::sbvh> g_scene;

static VoxelViewer g_viewer;
static aten::RasterizeRenderer g_rasterizer;

static aten::PinholeCamera g_camera;
static bool g_isCameraDirty = false;

static bool g_willShowGUI = true;

static int g_drawVoxelDepth = 1;
static bool g_drawMesh = false;
static bool g_isWireframe = false;

static bool g_isMouseLBtnDown = false;
static bool g_isMouseRBtnDown = false;
static int g_prevX = 0;
static int g_prevY = 0;

static std::vector<std::vector<aten::ThreadedSbvhNode>> g_voxels;

void onRun(aten::window* window)
{
	if (g_isCameraDirty) {
		g_camera.update();

		auto camparam = g_camera.param();
		camparam.znear = real(0.1);
		camparam.zfar = real(10000.0);

		g_isCameraDirty = false;
	}

	// TODO
	auto sbvh = (aten::sbvh*)g_objs[0]->getInternalAccelerator();

	if (g_voxels.empty()) {
		auto maxDepth = sbvh->getMaxDepth();
		g_voxels.resize(maxDepth);

		// NOTE
		// nodes[0] is top layer.
		const auto& nodes = g_scene.getAccel()->getNodes();
		g_viewer.bringVoxels(nodes[1], g_voxels);
	}

	g_viewer.draw(
		&g_camera,
		g_voxels,
		g_isWireframe,
		g_drawVoxelDepth);

	if (g_drawMesh) {
		for (auto obj : g_objs) {
			g_rasterizer.draw(obj, &g_camera, false);
		}
	}

	{
		ImGui::SliderInt("Depth", &g_drawVoxelDepth, 1, sbvh->getMaxDepth());
		ImGui::Checkbox("Wireframe,", &g_isWireframe);
		ImGui::Checkbox("Draw mesh,", &g_drawMesh);

		window->drawImGui();
	}
}

void onClose()
{

}

void onMouseBtn(bool left, bool press, int x, int y)
{
	g_isMouseLBtnDown = false;
	g_isMouseRBtnDown = false;

	if (press) {
		g_prevX = x;
		g_prevY = y;

		g_isMouseLBtnDown = left;
		g_isMouseRBtnDown = !left;
	}
}

void onMouseMove(int x, int y)
{
	if (g_isMouseLBtnDown) {
		aten::CameraOperator::rotate(
			g_camera,
			WIDTH, HEIGHT,
			g_prevX, g_prevY,
			x, y);
		g_isCameraDirty = true;
	}
	else if (g_isMouseRBtnDown) {
		aten::CameraOperator::move(
			g_camera,
			g_prevX, g_prevY,
			x, y,
			real(0.001));
		g_isCameraDirty = true;
	}

	g_prevX = x;
	g_prevY = y;
}

void onMouseWheel(int delta)
{
	aten::CameraOperator::dolly(g_camera, delta * real(0.1));
	g_isCameraDirty = true;
}

void onKey(bool press, aten::Key key)
{
	static const real offset = real(0.1);

	if (press) {
		if (key == aten::Key::Key_F1) {
			g_willShowGUI = !g_willShowGUI;
			return;
		}
	}

	if (press) {
		switch (key) {
		case aten::Key::Key_W:
		case aten::Key::Key_UP:
			aten::CameraOperator::moveForward(g_camera, offset);
			break;
		case aten::Key::Key_S:
		case aten::Key::Key_DOWN:
			aten::CameraOperator::moveForward(g_camera, -offset);
			break;
		case aten::Key::Key_D:
		case aten::Key::Key_RIGHT:
			aten::CameraOperator::moveRight(g_camera, offset);
			break;
		case aten::Key::Key_A:
		case aten::Key::Key_LEFT:
			aten::CameraOperator::moveRight(g_camera, -offset);
			break;
		case aten::Key::Key_Z:
			aten::CameraOperator::moveUp(g_camera, offset);
			break;
		case aten::Key::Key_X:
			aten::CameraOperator::moveUp(g_camera, -offset);
			break;
		default:
			break;
		}

		g_isCameraDirty = true;
	}
}

bool parseOption(
	int argc, char* argv[],
	cmdline::parser& cmd,
	Options& opt)
{
	{
		cmd.add<std::string>("input", 'i', "input filename", true);
		cmd.add<std::string>("output", 'o', "output filename base", false, "result");

		cmd.add<std::string>("help", '?', "print usage", false);
	}

	bool isCmdOk = cmd.parse(argc, argv);

	if (cmd.exist("help")) {
		std::cerr << cmd.usage();
		return false;
	}

	if (!isCmdOk) {
		std::cerr << cmd.error() << std::endl << cmd.usage();
		return false;
	}

	if (cmd.exist("input")) {
		opt.input = cmd.get<std::string>("input");
	}
	else {
		std::cerr << cmd.error() << std::endl << cmd.usage();
		return false;
	}

	if (cmd.exist("output")) {
		opt.output = cmd.get<std::string>("output");
	}
	else {
		// TODO
		opt.output = "result.sbvh";
	}

	return true;
}

// TODO
void loadObj(const Options& opt)
{
#if 0
	auto emit = new aten::emissive(aten::vec3(36, 33, 24));
	aten::AssetManager::registerMtrl(
		"light",
		emit);

	aten::ObjLoader::load(g_objs, opt.input);
#elif 1
	aten::AssetManager::registerMtrl(
		"m",
		//new aten::lambert(aten::vec3(0.580000, 0.580000, 0.580000)));
		new aten::MicrofacetGGX(aten::vec3(0.7, 0.7, 0.7), 0.2, 0.2));

	aten::ObjLoader::load(g_objs, opt.input);
#else
	aten::ObjLoader::load(g_objs, "../../asset/sponza/sponza.obj");

	g_objs[0]->importInternalAccelTree("../../asset/sponza/sponza.sbvh");
#endif

	for (auto obj : g_objs) {
		auto instance = new aten::instance<aten::object>(obj, aten::mat4::Identity);
		g_scene.add(instance);
	}

	g_scene.build();
}

int main(int argc, char* argv[])
{
	//g_opt.input = "../../asset/cornellbox/orig.obj";
	//g_opt.input = "../../asset/sponza/lod.obj";
	//g_opt.input = "../../asset/suzanne/suzanne.obj";
	g_opt.input = "../../asset/bunny/bunny.obj";

	// TODO
#if 0
	cmdline::parser cmd;

	if (!parseOption(argc, argv, cmd, g_opt)) {
		return 0;
	}
#endif

	std::string extname;
	aten::getStringsFromPath(g_opt.input, g_opt.inputBasepath, extname, g_opt.inputFilename);

	aten::SetCurrentDirectoryFromExe();

	aten::AssetManager::suppressWarnings();

	aten::window::init(
		WIDTH, HEIGHT,
		TITLE,
		onRun,
		onClose,
		onMouseBtn,
		onMouseMove,
		onMouseWheel,
		onKey);

	loadObj(g_opt);

	aten::texture::initAllAsGLTexture();

	// TODO
	aten::vec3 pos(0, 1, 3);
	aten::vec3 at(0, 1, 0);
	real vfov = real(45);

	g_camera.init(
		pos,
		at,
		aten::vec3(0, 1, 0),
		vfov,
		WIDTH, HEIGHT);

	g_viewer.init(
		WIDTH, HEIGHT,
		"voxelviewer_vs.glsl",
		"voxelviewer_fs.glsl");

	g_rasterizer.init(
		WIDTH, HEIGHT,
		"../shader/drawobj_vs.glsl",
		"../shader/drawobj_fs.glsl");

	aten::window::run();

	aten::window::terminate();

	return 1;
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qgeoareamonitor_maemo_p.h"

QTM_BEGIN_NAMESPACE

#define UPDATE_INTERVAL_5S 5000

QGeoAreaMonitorMaemo::QGeoAreaMonitorMaemo(QObject *parent) : QGeoAreaMonitor(parent)
{
    insideArea = false;
    location = QGeoPositionInfoSource::createDefaultSource(this);
    if(location) {
        location->setUpdateInterval(UPDATE_INTERVAL_5S);
        connect(location, SIGNAL(positionUpdated(QGeoPositionInfo)),
                this, SLOT(positionUpdated(QGeoPositionInfo)));
        location->startUpdates();
    }
}

QGeoAreaMonitorMaemo::~QGeoAreaMonitorMaemo()
{
    if(location)
        location->stopUpdates();

}

void QGeoAreaMonitorMaemo::setCenter(const QGeoCoordinate& coordinate)
{
    if (coordinate.isValid())
        QGeoAreaMonitor::setCenter(coordinate);
}

void QGeoAreaMonitorMaemo::setRadius(qreal radius)
{
    QGeoAreaMonitor::setRadius(radius);
}

void QGeoAreaMonitorMaemo::positionUpdated(const QGeoPositionInfo &info)
{
    double distance =
            location_distance_between(info.coordinate().latitude(),
                                      info.coordinate().longitude(),
                                      QGeoAreaMonitor::center().latitude(),
                                      QGeoAreaMonitor::center().longitude());

    if (distance <= QGeoAreaMonitor::radius()) {
        if(!insideArea)
            emit areaEntered(info);
        insideArea = true;
    } else if (insideArea) {
        emit areaExited(info);
        insideArea = false;
    }
}

#include "moc_qgeoareamonitor_maemo_p.cpp"
QTM_END_NAMESPACE
<commit_msg>Distance scale correction.<commit_after>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qgeoareamonitor_maemo_p.h"

QTM_BEGIN_NAMESPACE

#define UPDATE_INTERVAL_5S  5000
#define TO_METERS           1000

QGeoAreaMonitorMaemo::QGeoAreaMonitorMaemo(QObject *parent) : QGeoAreaMonitor(parent)
{
    insideArea = false;
    location = QGeoPositionInfoSource::createDefaultSource(this);
    if(location) {
        location->setUpdateInterval(UPDATE_INTERVAL_5S);
        connect(location, SIGNAL(positionUpdated(QGeoPositionInfo)),
                this, SLOT(positionUpdated(QGeoPositionInfo)));
        location->startUpdates();
    }
}

QGeoAreaMonitorMaemo::~QGeoAreaMonitorMaemo()
{
    if(location)
        location->stopUpdates();

}

void QGeoAreaMonitorMaemo::setCenter(const QGeoCoordinate& coordinate)
{
    if (coordinate.isValid())
        QGeoAreaMonitor::setCenter(coordinate);
}

void QGeoAreaMonitorMaemo::setRadius(qreal radius)
{
    QGeoAreaMonitor::setRadius(radius);
}

void QGeoAreaMonitorMaemo::positionUpdated(const QGeoPositionInfo &info)
{
    double distance =
            location_distance_between(info.coordinate().latitude(),
                                      info.coordinate().longitude(),
                                      QGeoAreaMonitor::center().latitude(),
                                      QGeoAreaMonitor::center().longitude());

    distance = distance * TO_METERS;

    if (distance <= QGeoAreaMonitor::radius()) {
        if(!insideArea)
            emit areaEntered(info);
        insideArea = true;
    } else if (insideArea) {
        emit areaExited(info);
        insideArea = false;
    }
}

#include "moc_qgeoareamonitor_maemo_p.cpp"
QTM_END_NAMESPACE
<|endoftext|>


<commit_before><commit_msg>Makes app tabs use the app icon instead of favicon.<commit_after><|endoftext|>


<commit_before>// Copyright 2018 The SwiftShader Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "VkSurfaceKHR.hpp"

#include "Vulkan/VkDestroy.hpp"

#include <algorithm>

namespace {

static const VkSurfaceFormatKHR surfaceFormats[] = {
	{ VK_FORMAT_B8G8R8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR },
	{ VK_FORMAT_B8G8R8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR },
};

static const VkPresentModeKHR presentModes[] = {
	// FIXME(b/124265819): Make present modes behave correctly. Currently we use XPutImage
	// with no synchronization, which behaves more like VK_PRESENT_MODE_IMMEDIATE_KHR. We
	// should convert to using the Present extension, which allows us to request presentation
	// at particular msc values. Will need a similar solution on Windows - possibly interact
	// with DXGI directly.
	VK_PRESENT_MODE_FIFO_KHR,
	VK_PRESENT_MODE_MAILBOX_KHR,
};

}  // namespace

namespace vk {

VkResult PresentImage::allocateImage(VkDevice device, const VkImageCreateInfo &createInfo)
{
	VkImage *vkImagePtr = reinterpret_cast<VkImage *>(allocate(sizeof(VkImage), REQUIRED_MEMORY_ALIGNMENT, DEVICE_MEMORY));
	if(!vkImagePtr)
	{
		return VK_ERROR_OUT_OF_DEVICE_MEMORY;
	}

	VkResult status = vkCreateImage(device, &createInfo, nullptr, vkImagePtr);
	if(status != VK_SUCCESS)
	{
		deallocate(vkImagePtr, DEVICE_MEMORY);
		return status;
	}

	image = Cast(*vkImagePtr);
	deallocate(vkImagePtr, DEVICE_MEMORY);

	return status;
}

VkResult PresentImage::allocateAndBindImageMemory(VkDevice device, const VkMemoryAllocateInfo &allocateInfo)
{
	ASSERT(image);

	VkDeviceMemory *vkDeviceMemoryPtr = reinterpret_cast<VkDeviceMemory *>(
	    allocate(sizeof(VkDeviceMemory), REQUIRED_MEMORY_ALIGNMENT, DEVICE_MEMORY));
	if(!vkDeviceMemoryPtr)
	{
		return VK_ERROR_OUT_OF_DEVICE_MEMORY;
	}

	VkResult status = vkAllocateMemory(device, &allocateInfo, nullptr, vkDeviceMemoryPtr);
	if(status != VK_SUCCESS)
	{
		deallocate(vkDeviceMemoryPtr, DEVICE_MEMORY);
		return status;
	}

	imageMemory = Cast(*vkDeviceMemoryPtr);
	vkBindImageMemory(device, *image, *vkDeviceMemoryPtr, 0);

	imageStatus = AVAILABLE;
	deallocate(vkDeviceMemoryPtr, DEVICE_MEMORY);

	return status;
}

void PresentImage::clear()
{
	if(imageMemory)
	{
		vk::destroy(static_cast<VkDeviceMemory>(*imageMemory), nullptr);
		imageMemory = nullptr;
	}

	if(image)
	{
		vk::destroy(static_cast<VkImage>(*image), nullptr);
		image = nullptr;
	}

	imageStatus = NONEXISTENT;
}

VkImage PresentImage::asVkImage() const
{
	return image ? static_cast<VkImage>(*image) : VkImage({ VK_NULL_HANDLE });
}

uint32_t SurfaceKHR::getSurfaceFormatsCount() const
{
	return static_cast<uint32_t>(sizeof(surfaceFormats) / sizeof(surfaceFormats[0]));
}

VkResult SurfaceKHR::getSurfaceFormats(uint32_t *pSurfaceFormatCount, VkSurfaceFormatKHR *pSurfaceFormats) const
{
	uint32_t count = getSurfaceFormatsCount();

	uint32_t i;
	for(i = 0; i < std::min(*pSurfaceFormatCount, count); i++)
	{
		pSurfaceFormats[i] = surfaceFormats[i];
	}

	*pSurfaceFormatCount = i;

	if(*pSurfaceFormatCount < count)
	{
		return VK_INCOMPLETE;
	}

	return VK_SUCCESS;
}

uint32_t SurfaceKHR::getPresentModeCount() const
{
	return static_cast<uint32_t>(sizeof(presentModes) / sizeof(presentModes[0]));
}

VkResult SurfaceKHR::getPresentModes(uint32_t *pPresentModeCount, VkPresentModeKHR *pPresentModes) const
{
	uint32_t count = getPresentModeCount();

	uint32_t i;
	for(i = 0; i < std::min(*pPresentModeCount, count); i++)
	{
		pPresentModes[i] = presentModes[i];
	}

	*pPresentModeCount = i;

	if(*pPresentModeCount < count)
	{
		return VK_INCOMPLETE;
	}

	return VK_SUCCESS;
}

void SurfaceKHR::associateSwapchain(SwapchainKHR *swapchain)
{
	associatedSwapchain = swapchain;
}

void SurfaceKHR::disassociateSwapchain()
{
	associatedSwapchain = nullptr;
}

bool SurfaceKHR::hasAssociatedSwapchain()
{
	return (associatedSwapchain != nullptr);
}

VkResult SurfaceKHR::getPresentRectangles(uint32_t *pRectCount, VkRect2D *pRects) const
{
	if(!pRects)
	{
		*pRectCount = 1;
		return VK_SUCCESS;
	}

	if(*pRectCount < 1)
	{
		return VK_INCOMPLETE;
	}

	VkSurfaceCapabilitiesKHR capabilities;
	getSurfaceCapabilities(&capabilities);

	pRects[0].offset = { 0, 0 };
	pRects[0].extent = capabilities.currentExtent;
	*pRectCount = 1;

	return VK_SUCCESS;
}

void SurfaceKHR::setCommonSurfaceCapabilities(VkSurfaceCapabilitiesKHR *pSurfaceCapabilities)
{
	pSurfaceCapabilities->minImageCount = 1;
	pSurfaceCapabilities->maxImageCount = 0;

	pSurfaceCapabilities->maxImageArrayLayers = 1;

	pSurfaceCapabilities->supportedTransforms = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
	pSurfaceCapabilities->currentTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
	pSurfaceCapabilities->supportedCompositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
	pSurfaceCapabilities->supportedUsageFlags =
	    VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
	    VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
	    VK_IMAGE_USAGE_TRANSFER_DST_BIT |
	    VK_IMAGE_USAGE_SAMPLED_BIT;
}

}  // namespace vk<commit_msg>Refactor swapchain image creation<commit_after>// Copyright 2018 The SwiftShader Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "VkSurfaceKHR.hpp"

#include "Vulkan/VkDestroy.hpp"

#include <algorithm>

namespace {

static const VkSurfaceFormatKHR surfaceFormats[] = {
	{ VK_FORMAT_B8G8R8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR },
	{ VK_FORMAT_B8G8R8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR },
};

static const VkPresentModeKHR presentModes[] = {
	// FIXME(b/124265819): Make present modes behave correctly. Currently we use XPutImage
	// with no synchronization, which behaves more like VK_PRESENT_MODE_IMMEDIATE_KHR. We
	// should convert to using the Present extension, which allows us to request presentation
	// at particular msc values. Will need a similar solution on Windows - possibly interact
	// with DXGI directly.
	VK_PRESENT_MODE_FIFO_KHR,
	VK_PRESENT_MODE_MAILBOX_KHR,
};

}  // namespace

namespace vk {

VkResult PresentImage::allocateImage(VkDevice device, const VkImageCreateInfo &createInfo)
{
	VkImage image;
	VkResult status = vkCreateImage(device, &createInfo, nullptr, &image);
	if(status != VK_SUCCESS)
	{
		return status;
	}

	this->image = Cast(image);

	return status;
}

VkResult PresentImage::allocateAndBindImageMemory(VkDevice device, const VkMemoryAllocateInfo &allocateInfo)
{
	ASSERT(image);

	VkDeviceMemory deviceMemory;
	VkResult status = vkAllocateMemory(device, &allocateInfo, nullptr, &deviceMemory);
	if(status != VK_SUCCESS)
	{
		return status;
	}

	imageMemory = Cast(deviceMemory);
	vkBindImageMemory(device, *image, deviceMemory, 0);
	imageStatus = AVAILABLE;

	return VK_SUCCESS;
}

void PresentImage::clear()
{
	if(imageMemory)
	{
		vk::destroy(static_cast<VkDeviceMemory>(*imageMemory), nullptr);
		imageMemory = nullptr;
	}

	if(image)
	{
		vk::destroy(static_cast<VkImage>(*image), nullptr);
		image = nullptr;
	}

	imageStatus = NONEXISTENT;
}

VkImage PresentImage::asVkImage() const
{
	return image ? static_cast<VkImage>(*image) : VkImage({ VK_NULL_HANDLE });
}

uint32_t SurfaceKHR::getSurfaceFormatsCount() const
{
	return static_cast<uint32_t>(sizeof(surfaceFormats) / sizeof(surfaceFormats[0]));
}

VkResult SurfaceKHR::getSurfaceFormats(uint32_t *pSurfaceFormatCount, VkSurfaceFormatKHR *pSurfaceFormats) const
{
	uint32_t count = getSurfaceFormatsCount();

	uint32_t i;
	for(i = 0; i < std::min(*pSurfaceFormatCount, count); i++)
	{
		pSurfaceFormats[i] = surfaceFormats[i];
	}

	*pSurfaceFormatCount = i;

	if(*pSurfaceFormatCount < count)
	{
		return VK_INCOMPLETE;
	}

	return VK_SUCCESS;
}

uint32_t SurfaceKHR::getPresentModeCount() const
{
	return static_cast<uint32_t>(sizeof(presentModes) / sizeof(presentModes[0]));
}

VkResult SurfaceKHR::getPresentModes(uint32_t *pPresentModeCount, VkPresentModeKHR *pPresentModes) const
{
	uint32_t count = getPresentModeCount();

	uint32_t i;
	for(i = 0; i < std::min(*pPresentModeCount, count); i++)
	{
		pPresentModes[i] = presentModes[i];
	}

	*pPresentModeCount = i;

	if(*pPresentModeCount < count)
	{
		return VK_INCOMPLETE;
	}

	return VK_SUCCESS;
}

void SurfaceKHR::associateSwapchain(SwapchainKHR *swapchain)
{
	associatedSwapchain = swapchain;
}

void SurfaceKHR::disassociateSwapchain()
{
	associatedSwapchain = nullptr;
}

bool SurfaceKHR::hasAssociatedSwapchain()
{
	return (associatedSwapchain != nullptr);
}

VkResult SurfaceKHR::getPresentRectangles(uint32_t *pRectCount, VkRect2D *pRects) const
{
	if(!pRects)
	{
		*pRectCount = 1;
		return VK_SUCCESS;
	}

	if(*pRectCount < 1)
	{
		return VK_INCOMPLETE;
	}

	VkSurfaceCapabilitiesKHR capabilities;
	getSurfaceCapabilities(&capabilities);

	pRects[0].offset = { 0, 0 };
	pRects[0].extent = capabilities.currentExtent;
	*pRectCount = 1;

	return VK_SUCCESS;
}

void SurfaceKHR::setCommonSurfaceCapabilities(VkSurfaceCapabilitiesKHR *pSurfaceCapabilities)
{
	pSurfaceCapabilities->minImageCount = 1;
	pSurfaceCapabilities->maxImageCount = 0;

	pSurfaceCapabilities->maxImageArrayLayers = 1;

	pSurfaceCapabilities->supportedTransforms = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
	pSurfaceCapabilities->currentTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
	pSurfaceCapabilities->supportedCompositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
	pSurfaceCapabilities->supportedUsageFlags =
	    VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
	    VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
	    VK_IMAGE_USAGE_TRANSFER_DST_BIT |
	    VK_IMAGE_USAGE_SAMPLED_BIT;
}

}  // namespace vk<|endoftext|>


<commit_before>//Copyright (c) 2020 Ultimaker B.V.
//CuraEngine is released under the terms of the AGPLv3 or higher.

#include "ExtruderTrain.h"
#include "sliceDataStorage.h"
#include "WallsComputation.h"
#include "settings/types/Ratio.h"
#include "settings/EnumSettings.h"
#include "utils/polygonUtils.h"

// libArachne
#include "SkeletalTrapezoidation.h"
#include "BeadingStrategy/BeadingStrategyFactory.h"

namespace cura {

WallsComputation::WallsComputation(const Settings& settings, const LayerIndex layer_nr)
: settings(settings)
, layer_nr(layer_nr)
{
}

/*
 * This function is executed in a parallel region based on layer_nr.
 * When modifying make sure any changes does not introduce data races.
 *
 * generateInsets only reads and writes data for the current layer
 */
void WallsComputation::generateInsets(SliceLayerPart* part)
{
    size_t inset_count = settings.get<size_t>("wall_line_count");
    const bool spiralize = settings.get<bool>("magic_spiralize");
    if (spiralize && layer_nr < LayerIndex(settings.get<size_t>("initial_bottom_layers")) && ((layer_nr % 2) + 2) % 2 == 1) //Add extra insets every 2 layers when spiralizing. This makes bottoms of cups watertight.
    {
        inset_count += 5;
    }
    if (settings.get<bool>("alternate_extra_perimeter"))
    {
        inset_count += ((layer_nr % 2) + 2) % 2;
    }

    if (inset_count == 0)
    {
        part->insets.push_back(part->outline);
        part->print_outline = part->outline;
        return;
    }

    const coord_t wall_0_inset = settings.get<coord_t>("wall_0_inset");
    coord_t line_width_0 = settings.get<coord_t>("wall_line_width_0");
    coord_t line_width_x = settings.get<coord_t>("wall_line_width_x");
    if (layer_nr == 0)
    {
        const ExtruderTrain& train_wall_0 = settings.get<ExtruderTrain&>("wall_0_extruder_nr");
        line_width_0 *= train_wall_0.settings.get<Ratio>("initial_layer_line_width_factor");
        const ExtruderTrain& train_wall_x = settings.get<ExtruderTrain&>("wall_x_extruder_nr");
        line_width_x *= train_wall_x.settings.get<Ratio>("initial_layer_line_width_factor");
    }

    const bool recompute_outline_based_on_outer_wall =
        settings.get<bool>("support_enable") &&
        !settings.get<bool>("fill_outline_gaps");
    for(size_t i = 0; i < inset_count; i++)
    {
        part->insets.push_back(Polygons());
        if (i == 0)
        {
            part->insets[0] = part->outline.offset(-line_width_0 / 2 - wall_0_inset);
        }
        else if (i == 1)
        {
            part->insets[1] = part->insets[0].offset(-line_width_0 / 2 + wall_0_inset - line_width_x / 2);
        }
        else
        {
            part->insets[i] = part->insets[i - 1].offset(-line_width_x);
        }

        const size_t inset_part_count = part->insets[i].size();
        constexpr size_t minimum_part_saving = 3; //Only try if the part has more pieces than the previous inset and saves at least this many parts.
        constexpr coord_t try_smaller = 10; //How many micrometres to inset with the try with a smaller inset.
        if (inset_part_count > minimum_part_saving + 1 && (i == 0 || (i > 0 && inset_part_count > part->insets[i - 1].size() + minimum_part_saving)))
        {
            //Try a different line thickness and see if this fits better, based on these criteria:
            // - There are fewer parts to the polygon (fits better in slim areas).
            // - The polygon area is largely unaffected.
            Polygons alternative_inset;
            if (i == 0)
            {
                alternative_inset = part->outline.offset(-(line_width_0 - try_smaller) / 2 - wall_0_inset);
            }
            else if (i == 1)
            {
                alternative_inset = part->insets[0].offset(-(line_width_0 - try_smaller) / 2 + wall_0_inset - line_width_x / 2);
            }
            else
            {
                alternative_inset = part->insets[i - 1].offset(-(line_width_x - try_smaller));
            }
            if (alternative_inset.size() < inset_part_count - minimum_part_saving) //Significantly fewer parts (saves more than 3 parts).
            {
                part->insets[i] = alternative_inset;
            }
        }

        //Finally optimize all the polygons. Every point removed saves time in the long run.
        part->insets[i].simplify();
        part->insets[i].removeDegenerateVerts();
        if (i == 0)
        {
            if (recompute_outline_based_on_outer_wall)
            {
                part->print_outline = part->insets[0].offset(line_width_0 / 2, ClipperLib::jtSquare);
            }
            else
            {
                part->print_outline = part->outline;
            }
        }
        if (part->insets[i].size() < 1)
        {
            part->insets.pop_back();
            break;
        }
    }

    // Call on libArachne:
    auto strategy_type = settings.get<StrategyType>("beading_strategy_type");

    coord_t* min_bead_width = nullptr;
    coord_t* min_feature_size = nullptr;
    if (settings.get<bool>("widening_beading_enabled"))
    {
        min_bead_width = new coord_t(settings.get<coord_t>("min_bead_width"));
        min_feature_size = new coord_t(settings.get<coord_t>("min_feature_size"));
    }

    constexpr float transitioning_angle = 0.5;
    const coord_t transition_length = 2 * std::max(line_width_0, line_width_x);
    constexpr coord_t smallest_segment = 50;
    constexpr coord_t allowed_distance = 50;
    constexpr coord_t epsilon_offset = (allowed_distance / 2) - 1;

    const double small_area_length = INT2MM(line_width_0 / 2);
    Polygons prepared_outline = part->outline.offset(-epsilon_offset).offset(epsilon_offset);
    prepared_outline.simplify(smallest_segment, allowed_distance);
    PolygonUtils::fixSelfIntersections(epsilon_offset, prepared_outline);
    prepared_outline.removeDegenerateVerts();
    prepared_outline.removeColinearEdges();
    prepared_outline.removeSmallAreas(small_area_length * small_area_length, false); // TODO: complete guess as to when arachne starts breaking, but it doesn't function well when an area is really small apearantly?
    if (prepared_outline.area() > 0)
    {
        const BeadingStrategy* beading_strat = BeadingStrategyFactory::makeStrategy(strategy_type, line_width_0, line_width_x, transition_length, transitioning_angle, min_bead_width, min_feature_size, 2 * inset_count); // TODO: deal with beading-strats & (their) magic parameters
        SkeletalTrapezoidation wall_maker(prepared_outline, *beading_strat, beading_strat->transitioning_angle);
        wall_maker.generateToolpaths(part->wall_toolpaths);
        delete beading_strat;
    }
    delete min_bead_width;
    delete min_feature_size;
}

/*
 * This function is executed in a parallel region based on layer_nr.
 * When modifying make sure any changes does not introduce data races.
 *
 * generateInsets only reads and writes data for the current layer
 */
void WallsComputation::generateInsets(SliceLayer* layer)
{
    for(unsigned int partNr = 0; partNr < layer->parts.size(); partNr++)
    {
        generateInsets(&layer->parts[partNr]);
    }

    const bool remove_parts_with_no_insets = !settings.get<bool>("fill_outline_gaps");
    //Remove the parts which did not generate an inset. As these parts are too small to print,
    // and later code can now assume that there is always minimal 1 inset line.
    for (unsigned int part_idx = 0; part_idx < layer->parts.size(); part_idx++)
    {
        if (layer->parts[part_idx].insets.size() == 0 && remove_parts_with_no_insets)
        {
            if (part_idx != layer->parts.size() - 1)
            { // move existing part into part to be deleted
                layer->parts[part_idx] = std::move(layer->parts.back());
            }
            layer->parts.pop_back(); // always remove last element from array (is more efficient)
            part_idx -= 1; // check the part we just moved here
        }
    }
}

}//namespace cura
<commit_msg>Alter comments to reflect current arachne status.<commit_after>//Copyright (c) 2020 Ultimaker B.V.
//CuraEngine is released under the terms of the AGPLv3 or higher.

#include "ExtruderTrain.h"
#include "sliceDataStorage.h"
#include "WallsComputation.h"
#include "settings/types/Ratio.h"
#include "settings/EnumSettings.h"
#include "utils/polygonUtils.h"

// libArachne
#include "SkeletalTrapezoidation.h"
#include "BeadingStrategy/BeadingStrategyFactory.h"

namespace cura {

WallsComputation::WallsComputation(const Settings& settings, const LayerIndex layer_nr)
: settings(settings)
, layer_nr(layer_nr)
{
}

/*
 * This function is executed in a parallel region based on layer_nr.
 * When modifying make sure any changes does not introduce data races.
 *
 * generateInsets only reads and writes data for the current layer
 */
void WallsComputation::generateInsets(SliceLayerPart* part)
{
    size_t inset_count = settings.get<size_t>("wall_line_count");
    const bool spiralize = settings.get<bool>("magic_spiralize");
    if (spiralize && layer_nr < LayerIndex(settings.get<size_t>("initial_bottom_layers")) && ((layer_nr % 2) + 2) % 2 == 1) //Add extra insets every 2 layers when spiralizing. This makes bottoms of cups watertight.
    {
        inset_count += 5;
    }
    if (settings.get<bool>("alternate_extra_perimeter"))
    {
        inset_count += ((layer_nr % 2) + 2) % 2;
    }

    if (inset_count == 0)
    {
        part->insets.push_back(part->outline);
        part->print_outline = part->outline;
        return;
    }

    const coord_t wall_0_inset = settings.get<coord_t>("wall_0_inset");
    coord_t line_width_0 = settings.get<coord_t>("wall_line_width_0");
    coord_t line_width_x = settings.get<coord_t>("wall_line_width_x");
    if (layer_nr == 0)
    {
        const ExtruderTrain& train_wall_0 = settings.get<ExtruderTrain&>("wall_0_extruder_nr");
        line_width_0 *= train_wall_0.settings.get<Ratio>("initial_layer_line_width_factor");
        const ExtruderTrain& train_wall_x = settings.get<ExtruderTrain&>("wall_x_extruder_nr");
        line_width_x *= train_wall_x.settings.get<Ratio>("initial_layer_line_width_factor");
    }

    const bool recompute_outline_based_on_outer_wall =
        settings.get<bool>("support_enable") &&
        !settings.get<bool>("fill_outline_gaps");
    for(size_t i = 0; i < inset_count; i++)
    {
        part->insets.push_back(Polygons());
        if (i == 0)
        {
            part->insets[0] = part->outline.offset(-line_width_0 / 2 - wall_0_inset);
        }
        else if (i == 1)
        {
            part->insets[1] = part->insets[0].offset(-line_width_0 / 2 + wall_0_inset - line_width_x / 2);
        }
        else
        {
            part->insets[i] = part->insets[i - 1].offset(-line_width_x);
        }

        const size_t inset_part_count = part->insets[i].size();
        constexpr size_t minimum_part_saving = 3; //Only try if the part has more pieces than the previous inset and saves at least this many parts.
        constexpr coord_t try_smaller = 10; //How many micrometres to inset with the try with a smaller inset.
        if (inset_part_count > minimum_part_saving + 1 && (i == 0 || (i > 0 && inset_part_count > part->insets[i - 1].size() + minimum_part_saving)))
        {
            //Try a different line thickness and see if this fits better, based on these criteria:
            // - There are fewer parts to the polygon (fits better in slim areas).
            // - The polygon area is largely unaffected.
            Polygons alternative_inset;
            if (i == 0)
            {
                alternative_inset = part->outline.offset(-(line_width_0 - try_smaller) / 2 - wall_0_inset);
            }
            else if (i == 1)
            {
                alternative_inset = part->insets[0].offset(-(line_width_0 - try_smaller) / 2 + wall_0_inset - line_width_x / 2);
            }
            else
            {
                alternative_inset = part->insets[i - 1].offset(-(line_width_x - try_smaller));
            }
            if (alternative_inset.size() < inset_part_count - minimum_part_saving) //Significantly fewer parts (saves more than 3 parts).
            {
                part->insets[i] = alternative_inset;
            }
        }

        //Finally optimize all the polygons. Every point removed saves time in the long run.
        part->insets[i].simplify();
        part->insets[i].removeDegenerateVerts();
        if (i == 0)
        {
            if (recompute_outline_based_on_outer_wall)
            {
                part->print_outline = part->insets[0].offset(line_width_0 / 2, ClipperLib::jtSquare);
            }
            else
            {
                part->print_outline = part->outline;
            }
        }
        if (part->insets[i].size() < 1)
        {
            part->insets.pop_back();
            break;
        }
    }

    // Call on libArachne:
    auto strategy_type = settings.get<StrategyType>("beading_strategy_type");

    coord_t* min_bead_width = nullptr;
    coord_t* min_feature_size = nullptr;
    if (settings.get<bool>("widening_beading_enabled"))
    {
        min_bead_width = new coord_t(settings.get<coord_t>("min_bead_width"));
        min_feature_size = new coord_t(settings.get<coord_t>("min_feature_size"));
    }

    constexpr float transitioning_angle = 0.5;
    const coord_t transition_length = 2 * std::max(line_width_0, line_width_x);
    constexpr coord_t smallest_segment = 50;
    constexpr coord_t allowed_distance = 50;
    constexpr coord_t epsilon_offset = (allowed_distance / 2) - 1;

    // Simplify outline for boost::voronoi consumption. Absolutely no self intersections or near-self instersections allowed:
    // TODO: Open question: Does this indeed fix all (or all-but-one-in-a-million) cases for manifold but otherwise possibly complex polygons?
    const double small_area_length = INT2MM(line_width_0 / 2);
    Polygons prepared_outline = part->outline.offset(-epsilon_offset).offset(epsilon_offset);
    prepared_outline.simplify(smallest_segment, allowed_distance);
    PolygonUtils::fixSelfIntersections(epsilon_offset, prepared_outline);
    prepared_outline.removeDegenerateVerts();
    prepared_outline.removeColinearEdges();
    prepared_outline.removeSmallAreas(small_area_length * small_area_length, false);
    if (prepared_outline.area() > 0)
    {
        // If there are indeed walls to generate, choose a beading-strategy and use libArachne to generate the toolpaths:
        const BeadingStrategy* beading_strat = BeadingStrategyFactory::makeStrategy(strategy_type, line_width_0, line_width_x, transition_length, transitioning_angle, min_bead_width, min_feature_size, 2 * inset_count);
        SkeletalTrapezoidation wall_maker(prepared_outline, *beading_strat, beading_strat->transitioning_angle);
        wall_maker.generateToolpaths(part->wall_toolpaths);
        delete beading_strat;
    }
    delete min_bead_width;
    delete min_feature_size;
}

/*
 * This function is executed in a parallel region based on layer_nr.
 * When modifying make sure any changes does not introduce data races.
 *
 * generateInsets only reads and writes data for the current layer
 */
void WallsComputation::generateInsets(SliceLayer* layer)
{
    for(unsigned int partNr = 0; partNr < layer->parts.size(); partNr++)
    {
        generateInsets(&layer->parts[partNr]);
    }

    const bool remove_parts_with_no_insets = !settings.get<bool>("fill_outline_gaps");
    //Remove the parts which did not generate an inset. As these parts are too small to print,
    // and later code can now assume that there is always minimal 1 inset line.
    for (unsigned int part_idx = 0; part_idx < layer->parts.size(); part_idx++)
    {
        if (layer->parts[part_idx].insets.size() == 0 && remove_parts_with_no_insets)
        {
            if (part_idx != layer->parts.size() - 1)
            { // move existing part into part to be deleted
                layer->parts[part_idx] = std::move(layer->parts.back());
            }
            layer->parts.pop_back(); // always remove last element from array (is more efficient)
            part_idx -= 1; // check the part we just moved here
        }
    }
}

}//namespace cura
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2008-2016 the MRtrix3 contributors
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/
 *
 * MRtrix is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 * For more details, see www.mrtrix.org
 *
 */

#include "command.h"
#include "image.h"
#include <Eigen/Dense>
#include <Eigen/SVD>

#define DEFAULT_SIZE 5

using namespace MR;
using namespace App;

void usage ()
{
  DESCRIPTION
  + "denoise DWI data and estimate the noise level based on the optimal threshold for PCA.";

  AUTHOR = "Daan Christiaens (daan.christiaens@kuleuven.be) & Jelle Veraart (jelle.veraart@nyumc.org) & J-Donald Tournier (jdtournier.gmail.com)";

  ARGUMENTS
  + Argument ("dwi", "the input diffusion-weighted image.").type_image_in ()

  + Argument ("out", "the output denoised DWI image.").type_image_out ();

  OPTIONS
    + Option ("mask", "only perform computation within the specified binary brain mask image.")
    +   Argument ("image").type_image_in()

    + Option ("size", "set the window size of the denoising filter. (default = " + str(DEFAULT_SIZE) + ")")
    +   Argument ("window").type_integer (0, 50)

    + Option ("noise", "the output noise map.")
    +   Argument ("level").type_image_out();

}

typedef float value_type;

template <class ImageType>
class DenoisingFunctor
{
  public:
  DenoisingFunctor (ImageType& dwi, int size, Image<bool>& mask, ImageType& noise)
    : extent(size/2),
      m(dwi.size(3)),
      n(size*size*size),
      r((m<n) ? m : n),
      X(m,n),
      pos{{0, 0, 0}},
      mask (mask),
      noise (noise)
  { }

  void operator () (ImageType& dwi, ImageType& out)
  {
    if (mask.valid()) {
      assign_pos_of (dwi).to (mask);
      if (!mask.value())
        return;
    }

    // Load data in local window
    load_data(dwi);

    // Compute SVD
    Eigen::JacobiSVD<Eigen::MatrixXf> svd (X, Eigen::ComputeThinU | Eigen::ComputeThinV);
    Eigen::VectorXf s = svd.singularValues();

    // Marchenko-Pastur optimal threshold
    const double lam_r = s[r-1]*s[r-1] / n;
    double clam = 0.0;
    sigma2 = NaN;
    for (ssize_t p = r-1; p >= 0; --p)
    {
      double lam = s[p]*s[p] / n;
      clam += lam;
      double gam = double(m-p) / double(n);
      double sigsq1 = clam / (r-p) / ((gam<1.0) ? 1.0 : gam);
      double sigsq2 = (lam - lam_r) / 4 / std::sqrt(gam);
      // sigsq2 > sigsq1 if signal else noise
      if (sigsq2 < sigsq1) {
        sigma2 = sigsq1;
        s[p] = 0.0;
      }
      else {
        break;
      }
    }

    // Restore DWI data
    X = svd.matrixU() * s.asDiagonal() * svd.matrixV().adjoint();

    // Store output
    assign_pos_of(dwi).to(out);
    for (auto l = Loop (3) (out); l; ++l)
      out.value() = X(out.index(3), n/2);

    if (noise.valid()) {
      assign_pos_of(dwi).to(noise);
      noise.value() = value_type (std::sqrt(sigma2));
    }
  }

  void load_data (ImageType& dwi)
  {
    pos[0] = dwi.index(0); pos[1] = dwi.index(1); pos[2] = dwi.index(2);
    X.setZero();
    ssize_t k = 0;
    for (dwi.index(2) = pos[2]-extent; dwi.index(2) <= pos[2]+extent; ++dwi.index(2))
      for (dwi.index(1) = pos[1]-extent; dwi.index(1) <= pos[1]+extent; ++dwi.index(1))
        for (dwi.index(0) = pos[0]-extent; dwi.index(0) <= pos[0]+extent; ++dwi.index(0), ++k)
          if (! is_out_of_bounds(dwi))
            X.col(k) = dwi.row(3).template cast<float>();
    // reset image position
    dwi.index(0) = pos[0];
    dwi.index(1) = pos[1];
    dwi.index(2) = pos[2];
  }

private:
  const int extent;
  const size_t m, n, r;
  Eigen::MatrixXf X;
  std::array<ssize_t, 3> pos;
  double sigma2;
  Image<bool> mask;
  ImageType noise;

};

void run ()
{
  auto dwi_in = Image<value_type>::open (argument[0]).with_direct_io(3);

  Image<bool> mask;
  auto opt = get_options ("mask");
  if (opt.size()) {
    mask = Image<bool>::open (opt[0][0]);
    check_dimensions (mask, dwi_in, 0, 3);
  }

  auto header = Header (dwi_in);
  header.datatype() = DataType::Float32;
  auto dwi_out = Image<value_type>::create (argument[1], header);

  int extent = get_option_value("size", DEFAULT_SIZE);

  Image<value_type> noise;
  opt = get_options("noise");
  if (opt.size()) {
    header.set_ndim(3);
    noise = Image<value_type>::create (opt[0][0], header);
  }

  DenoisingFunctor< Image<value_type> > func (dwi_in, extent, mask, noise);
  ThreadedLoop ("running MP-PCA denoising", dwi_in, 0, 3)
    .run (func, dwi_in, dwi_out);
}

<commit_msg>dwidenoise: rename option 'size' to 'extent'<commit_after>/*
 * Copyright (c) 2008-2016 the MRtrix3 contributors
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/
 *
 * MRtrix is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 * For more details, see www.mrtrix.org
 *
 */

#include "command.h"
#include "image.h"
#include <Eigen/Dense>
#include <Eigen/SVD>

#define DEFAULT_SIZE 5

using namespace MR;
using namespace App;

void usage ()
{
  DESCRIPTION
  + "denoise DWI data and estimate the noise level based on the optimal threshold for PCA.";

  AUTHOR = "Daan Christiaens (daan.christiaens@kuleuven.be) & Jelle Veraart (jelle.veraart@nyumc.org) & J-Donald Tournier (jdtournier.gmail.com)";

  ARGUMENTS
  + Argument ("dwi", "the input diffusion-weighted image.").type_image_in ()

  + Argument ("out", "the output denoised DWI image.").type_image_out ();

  OPTIONS
    + Option ("mask", "only perform computation within the specified binary brain mask image.")
    +   Argument ("image").type_image_in()

    + Option ("extent", "set the window size of the denoising filter. (default = " + str(DEFAULT_SIZE) + ")")
    +   Argument ("window").type_integer (0, 50)

    + Option ("noise", "the output noise map.")
    +   Argument ("level").type_image_out();

}

typedef float value_type;

template <class ImageType>
class DenoisingFunctor
{
  public:
  DenoisingFunctor (ImageType& dwi, int extent, Image<bool>& mask, ImageType& noise)
    : extent (extent/2),
      m (dwi.size(3)),
      n (extent*extent*extent),
      r ((m<n) ? m : n),
      X (m,n),
      pos {{0, 0, 0}},
      mask (mask),
      noise (noise)
  { }

  void operator () (ImageType& dwi, ImageType& out)
  {
    if (mask.valid()) {
      assign_pos_of (dwi).to (mask);
      if (!mask.value())
        return;
    }

    // Load data in local window
    load_data(dwi);

    // Compute SVD
    Eigen::JacobiSVD<Eigen::MatrixXf> svd (X, Eigen::ComputeThinU | Eigen::ComputeThinV);
    Eigen::VectorXf s = svd.singularValues();

    // Marchenko-Pastur optimal threshold
    const double lam_r = s[r-1]*s[r-1] / n;
    double clam = 0.0;
    sigma2 = NaN;
    for (ssize_t p = r-1; p >= 0; --p)
    {
      double lam = s[p]*s[p] / n;
      clam += lam;
      double gam = double(m-p) / double(n);
      double sigsq1 = clam / (r-p) / ((gam<1.0) ? 1.0 : gam);
      double sigsq2 = (lam - lam_r) / 4 / std::sqrt(gam);
      // sigsq2 > sigsq1 if signal else noise
      if (sigsq2 < sigsq1) {
        sigma2 = sigsq1;
        s[p] = 0.0;
      }
      else {
        break;
      }
    }

    // Restore DWI data
    X = svd.matrixU() * s.asDiagonal() * svd.matrixV().adjoint();

    // Store output
    assign_pos_of(dwi).to(out);
    for (auto l = Loop (3) (out); l; ++l)
      out.value() = X(out.index(3), n/2);

    if (noise.valid()) {
      assign_pos_of(dwi).to(noise);
      noise.value() = value_type (std::sqrt(sigma2));
    }
  }

  void load_data (ImageType& dwi)
  {
    pos[0] = dwi.index(0); pos[1] = dwi.index(1); pos[2] = dwi.index(2);
    X.setZero();
    ssize_t k = 0;
    for (dwi.index(2) = pos[2]-extent; dwi.index(2) <= pos[2]+extent; ++dwi.index(2))
      for (dwi.index(1) = pos[1]-extent; dwi.index(1) <= pos[1]+extent; ++dwi.index(1))
        for (dwi.index(0) = pos[0]-extent; dwi.index(0) <= pos[0]+extent; ++dwi.index(0), ++k)
          if (! is_out_of_bounds(dwi))
            X.col(k) = dwi.row(3).template cast<float>();
    // reset image position
    dwi.index(0) = pos[0];
    dwi.index(1) = pos[1];
    dwi.index(2) = pos[2];
  }

private:
  const int extent;
  const size_t m, n, r;
  Eigen::MatrixXf X;
  std::array<ssize_t, 3> pos;
  double sigma2;
  Image<bool> mask;
  ImageType noise;

};

void run ()
{
  auto dwi_in = Image<value_type>::open (argument[0]).with_direct_io(3);

  Image<bool> mask;
  auto opt = get_options ("mask");
  if (opt.size()) {
    mask = Image<bool>::open (opt[0][0]);
    check_dimensions (mask, dwi_in, 0, 3);
  }

  auto header = Header (dwi_in);
  header.datatype() = DataType::Float32;
  auto dwi_out = Image<value_type>::create (argument[1], header);

  int extent = get_option_value("extent", DEFAULT_SIZE);
  if (!(extent & 1))
    throw Exception ("-extent must be an odd number");

  Image<value_type> noise;
  opt = get_options("noise");
  if (opt.size()) {
    header.set_ndim(3);
    noise = Image<value_type>::create (opt[0][0], header);
  }

  DenoisingFunctor< Image<value_type> > func (dwi_in, extent, mask, noise);
  ThreadedLoop ("running MP-PCA denoising", dwi_in, 0, 3)
    .run (func, dwi_in, dwi_out);
}

<|endoftext|>