<commit_before>// This file is distributed under the MIT license.
// See the LICENSE file for details.

#include <cassert>

#include "model.h"
#include "sg.h"

namespace visionaray
{
namespace sg
{

//-------------------------------------------------------------------------------------------------
// node
//

std::vector<node::node_pointer>& node::parents()
{
    return parents_;
}

std::vector<node::node_pointer> const& node::parents() const
{
    return parents_;
}

std::vector<node::node_pointer>& node::children()
{
    return children_;
}

std::vector<node::node_pointer> const& node::children() const
{
    return children_;
}

void node::add_child(node_pointer child)
{
    child->parents_.push_back(shared_from_this());
    children_.push_back(child);
}

//-------------------------------------------------------------------------------------------------
// transform
//

transform::transform()
    : matrix_(mat4::identity())
{
}

transform::transform(mat4 matrix)
    : matrix_(matrix)
{
}

void transform::set_matrix(mat4 matrix)
{
    matrix_ = matrix;
}

mat4 transform::get_matrix() const
{
    return matrix_;
}

//-------------------------------------------------------------------------------------------------
// triangle_mesh
//

//-------------------------------------------------------------------------------------------------
// sphere
//

//-------------------------------------------------------------------------------------------------
// node_visitor
//

node_visitor::node_visitor(traversal_type tt)
    : traversal_type_(tt)
{
}

void node_visitor::apply(node& n)
{
    if (traversal_type_ == TraverseChildren)
    {
        for (auto& c : n.children_)
        {
            c->accept(*this);
        }
    }
    else if (traversal_type_ == TraverseParents)
    {

        for (auto& p : n.parents_)
        {
            p->accept(*this);
        }
    }
}

void node_visitor::apply(transform& t)
{
    apply(static_cast<node&>(t));
}

void node_visitor::apply(triangle_mesh& tm)
{
    apply(static_cast<node&>(tm));
}

void node_visitor::apply(sphere& s)
{
    apply(static_cast<node&>(s));
}

//-------------------------------------------------------------------------------------------------
// flatten
//

struct flatten_visitor : node_visitor
{
    flatten_visitor(model& mod)
        : model_(mod)
    {
    }

    void apply(transform& t)
    {
        mat4 prev = current_transform;

        current_transform = t.get_matrix() * current_transform;

        node_visitor::apply(t);

        current_transform = prev;
    }

    void apply(triangle_mesh& tm)
    {
        // Matrix to transform normals
        mat4 trans_inv = inverse(transpose(current_transform));

        assert(tm.indices.size() % 3 == 0);

        for (size_t i = 0; i < tm.indices.size(); i += 3)
        {
            vec3 v1 = tm.vertices[tm.indices[i]].pos;
            vec3 v2 = tm.vertices[tm.indices[i + 1]].pos;
            vec3 v3 = tm.vertices[tm.indices[i + 2]].pos;

            vec3 n1 = tm.vertices[tm.indices[i]].normal;
            vec3 n2 = tm.vertices[tm.indices[i + 1]].normal;
            vec3 n3 = tm.vertices[tm.indices[i + 2]].normal;

            vec3 gn = normalize(cross(v2 - v1, v3 - v1));

            v1 = (current_transform * vec4(v1, 1.0f)).xyz();
            v2 = (current_transform * vec4(v2, 1.0f)).xyz();
            v3 = (current_transform * vec4(v3, 1.0f)).xyz();

            n1 = (trans_inv * vec4(n1, 1.0f)).xyz();
            n2 = (trans_inv * vec4(n2, 1.0f)).xyz();
            n3 = (trans_inv * vec4(n3, 1.0f)).xyz();

            gn = (trans_inv * vec4(gn, 1.0f)).xyz();

            basic_triangle<3, float> t(v1, v2 - v1, v3 - v1);
            t.prim_id = static_cast<unsigned>(model_.primitives.size());
            t.geom_id = 0; // TODO
            model_.primitives.push_back(t);

            model_.shading_normals.push_back(n1);
            model_.shading_normals.push_back(n2);
            model_.shading_normals.push_back(n3);

            model_.geometric_normals.push_back(gn);

            model_.bbox.insert(v1);
            model_.bbox.insert(v2);
            model_.bbox.insert(v3);
        }

        node_visitor::apply(tm);
    }

    void apply(sphere& s)
    {
        // Matrix to transform normals
        mat4 trans_inv = inverse(transpose(current_transform));

        // Create triangles from sphere
        int resolution = 64;

        for (int i = 0; i < resolution; ++i)
        {
            int x1 = i;
            int x2 = (i + 1) % resolution;

            float theta1 = x1 * constants::two_pi<float>() / resolution - constants::pi_over_two<float>();
            float theta2 = x2 * constants::two_pi<float>() / resolution - constants::pi_over_two<float>();

            for (int j = 0; j < resolution / 2; ++j)
            {
                int y1 = j;
                int y2 = (j + 1) % resolution;

                float phi1 = y1 * constants::two_pi<float>() / resolution;
                float phi2 = y2 * constants::two_pi<float>() / resolution;

                vec3 v1(cos(theta1) * cos(phi1), sin(theta1), cos(theta1) * sin(phi1));
                vec3 v2(cos(theta2) * cos(phi1), sin(theta2), cos(theta2) * sin(phi1));
                vec3 v3(cos(theta2) * cos(phi2), sin(theta2), cos(theta2) * sin(phi2));
                vec3 v4(cos(theta1) * cos(phi2), sin(theta1), cos(theta1) * sin(phi2));

                vec3 n1 = v1;
                vec3 n2 = v2;
                vec3 n3 = v3;
                vec3 n4 = v4;

                vec3 gn1 = normalize(cross(v2 - v1, v3 - v1));
                vec3 gn2 = normalize(cross(v3 - v1, v4 - v1));

                v1 = (current_transform * vec4(v1, 1.0f)).xyz();
                v2 = (current_transform * vec4(v2, 1.0f)).xyz();
                v3 = (current_transform * vec4(v3, 1.0f)).xyz();
                v4 = (current_transform * vec4(v4, 1.0f)).xyz();

                n1 = (trans_inv * vec4(n1, 1.0f)).xyz();
                n2 = (trans_inv * vec4(n2, 1.0f)).xyz();
                n3 = (trans_inv * vec4(n3, 1.0f)).xyz();
                n4 = (trans_inv * vec4(n4, 1.0f)).xyz();

                if (i >= resolution / 2)
                {
                    n1 *= -1.0f;
                    n2 *= -1.0f;
                    n3 *= -1.0f;
                    n4 *= -1.0f;
                }

                gn1 = (trans_inv * vec4(gn1, 1.0f)).xyz();
                gn2 = (trans_inv * vec4(gn2, 1.0f)).xyz();

                basic_triangle<3, float> t1(v1, v2 - v1, v3 - v1);
                t1.prim_id = static_cast<unsigned>(model_.primitives.size());
                t1.geom_id = 0; // TODO
                model_.primitives.push_back(t1);

                basic_triangle<3, float> t2(v1, v3 - v1, v4 - v1);
                t2.prim_id = static_cast<unsigned>(model_.primitives.size());
                t2.geom_id = 0; // TODO
                model_.primitives.push_back(t2);

                model_.shading_normals.push_back(n1);
                model_.shading_normals.push_back(n2);
                model_.shading_normals.push_back(n3);

                model_.shading_normals.push_back(n1);
                model_.shading_normals.push_back(n3);
                model_.shading_normals.push_back(n4);

                model_.geometric_normals.push_back(gn1);
                model_.geometric_normals.push_back(gn2);

                model_.bbox.insert(v1);
                model_.bbox.insert(v2);
                model_.bbox.insert(v3);
                model_.bbox.insert(v4);
            }
        }

        node_visitor::apply(s);
    }

    // The model to add triangles to
    model& model_;

    // Current transform w.r.t. transform nodes
    mat4 current_transform = mat4::identity();
};

void flatten(model& mod, node& root)
{
    flatten_visitor visitor(mod);
    root.accept(visitor);
    mod.materials.push_back({}); // TODO
}

} // sg
} // visionaray
<commit_msg>Remove comments<commit_after>// This file is distributed under the MIT license.
// See the LICENSE file for details.

#include <cassert>

#include "model.h"
#include "sg.h"

namespace visionaray
{
namespace sg
{

//-------------------------------------------------------------------------------------------------
// node
//

std::vector<node::node_pointer>& node::parents()
{
    return parents_;
}

std::vector<node::node_pointer> const& node::parents() const
{
    return parents_;
}

std::vector<node::node_pointer>& node::children()
{
    return children_;
}

std::vector<node::node_pointer> const& node::children() const
{
    return children_;
}

void node::add_child(node_pointer child)
{
    child->parents_.push_back(shared_from_this());
    children_.push_back(child);
}

//-------------------------------------------------------------------------------------------------
// transform
//

transform::transform()
    : matrix_(mat4::identity())
{
}

transform::transform(mat4 matrix)
    : matrix_(matrix)
{
}

void transform::set_matrix(mat4 matrix)
{
    matrix_ = matrix;
}

mat4 transform::get_matrix() const
{
    return matrix_;
}

//-------------------------------------------------------------------------------------------------
// node_visitor
//

node_visitor::node_visitor(traversal_type tt)
    : traversal_type_(tt)
{
}

void node_visitor::apply(node& n)
{
    if (traversal_type_ == TraverseChildren)
    {
        for (auto& c : n.children_)
        {
            c->accept(*this);
        }
    }
    else if (traversal_type_ == TraverseParents)
    {

        for (auto& p : n.parents_)
        {
            p->accept(*this);
        }
    }
}

void node_visitor::apply(transform& t)
{
    apply(static_cast<node&>(t));
}

void node_visitor::apply(triangle_mesh& tm)
{
    apply(static_cast<node&>(tm));
}

void node_visitor::apply(sphere& s)
{
    apply(static_cast<node&>(s));
}

//-------------------------------------------------------------------------------------------------
// flatten
//

struct flatten_visitor : node_visitor
{
    flatten_visitor(model& mod)
        : model_(mod)
    {
    }

    void apply(transform& t)
    {
        mat4 prev = current_transform;

        current_transform = t.get_matrix() * current_transform;

        node_visitor::apply(t);

        current_transform = prev;
    }

    void apply(triangle_mesh& tm)
    {
        // Matrix to transform normals
        mat4 trans_inv = inverse(transpose(current_transform));

        assert(tm.indices.size() % 3 == 0);

        for (size_t i = 0; i < tm.indices.size(); i += 3)
        {
            vec3 v1 = tm.vertices[tm.indices[i]].pos;
            vec3 v2 = tm.vertices[tm.indices[i + 1]].pos;
            vec3 v3 = tm.vertices[tm.indices[i + 2]].pos;

            vec3 n1 = tm.vertices[tm.indices[i]].normal;
            vec3 n2 = tm.vertices[tm.indices[i + 1]].normal;
            vec3 n3 = tm.vertices[tm.indices[i + 2]].normal;

            vec3 gn = normalize(cross(v2 - v1, v3 - v1));

            v1 = (current_transform * vec4(v1, 1.0f)).xyz();
            v2 = (current_transform * vec4(v2, 1.0f)).xyz();
            v3 = (current_transform * vec4(v3, 1.0f)).xyz();

            n1 = (trans_inv * vec4(n1, 1.0f)).xyz();
            n2 = (trans_inv * vec4(n2, 1.0f)).xyz();
            n3 = (trans_inv * vec4(n3, 1.0f)).xyz();

            gn = (trans_inv * vec4(gn, 1.0f)).xyz();

            basic_triangle<3, float> t(v1, v2 - v1, v3 - v1);
            t.prim_id = static_cast<unsigned>(model_.primitives.size());
            t.geom_id = 0; // TODO
            model_.primitives.push_back(t);

            model_.shading_normals.push_back(n1);
            model_.shading_normals.push_back(n2);
            model_.shading_normals.push_back(n3);

            model_.geometric_normals.push_back(gn);

            model_.bbox.insert(v1);
            model_.bbox.insert(v2);
            model_.bbox.insert(v3);
        }

        node_visitor::apply(tm);
    }

    void apply(sphere& s)
    {
        // Matrix to transform normals
        mat4 trans_inv = inverse(transpose(current_transform));

        // Create triangles from sphere
        int resolution = 64;

        for (int i = 0; i < resolution; ++i)
        {
            int x1 = i;
            int x2 = (i + 1) % resolution;

            float theta1 = x1 * constants::two_pi<float>() / resolution - constants::pi_over_two<float>();
            float theta2 = x2 * constants::two_pi<float>() / resolution - constants::pi_over_two<float>();

            for (int j = 0; j < resolution / 2; ++j)
            {
                int y1 = j;
                int y2 = (j + 1) % resolution;

                float phi1 = y1 * constants::two_pi<float>() / resolution;
                float phi2 = y2 * constants::two_pi<float>() / resolution;

                vec3 v1(cos(theta1) * cos(phi1), sin(theta1), cos(theta1) * sin(phi1));
                vec3 v2(cos(theta2) * cos(phi1), sin(theta2), cos(theta2) * sin(phi1));
                vec3 v3(cos(theta2) * cos(phi2), sin(theta2), cos(theta2) * sin(phi2));
                vec3 v4(cos(theta1) * cos(phi2), sin(theta1), cos(theta1) * sin(phi2));

                vec3 n1 = v1;
                vec3 n2 = v2;
                vec3 n3 = v3;
                vec3 n4 = v4;

                vec3 gn1 = normalize(cross(v2 - v1, v3 - v1));
                vec3 gn2 = normalize(cross(v3 - v1, v4 - v1));

                v1 = (current_transform * vec4(v1, 1.0f)).xyz();
                v2 = (current_transform * vec4(v2, 1.0f)).xyz();
                v3 = (current_transform * vec4(v3, 1.0f)).xyz();
                v4 = (current_transform * vec4(v4, 1.0f)).xyz();

                n1 = (trans_inv * vec4(n1, 1.0f)).xyz();
                n2 = (trans_inv * vec4(n2, 1.0f)).xyz();
                n3 = (trans_inv * vec4(n3, 1.0f)).xyz();
                n4 = (trans_inv * vec4(n4, 1.0f)).xyz();

                if (i >= resolution / 2)
                {
                    n1 *= -1.0f;
                    n2 *= -1.0f;
                    n3 *= -1.0f;
                    n4 *= -1.0f;
                }

                gn1 = (trans_inv * vec4(gn1, 1.0f)).xyz();
                gn2 = (trans_inv * vec4(gn2, 1.0f)).xyz();

                basic_triangle<3, float> t1(v1, v2 - v1, v3 - v1);
                t1.prim_id = static_cast<unsigned>(model_.primitives.size());
                t1.geom_id = 0; // TODO
                model_.primitives.push_back(t1);

                basic_triangle<3, float> t2(v1, v3 - v1, v4 - v1);
                t2.prim_id = static_cast<unsigned>(model_.primitives.size());
                t2.geom_id = 0; // TODO
                model_.primitives.push_back(t2);

                model_.shading_normals.push_back(n1);
                model_.shading_normals.push_back(n2);
                model_.shading_normals.push_back(n3);

                model_.shading_normals.push_back(n1);
                model_.shading_normals.push_back(n3);
                model_.shading_normals.push_back(n4);

                model_.geometric_normals.push_back(gn1);
                model_.geometric_normals.push_back(gn2);

                model_.bbox.insert(v1);
                model_.bbox.insert(v2);
                model_.bbox.insert(v3);
                model_.bbox.insert(v4);
            }
        }

        node_visitor::apply(s);
    }

    // The model to add triangles to
    model& model_;

    // Current transform w.r.t. transform nodes
    mat4 current_transform = mat4::identity();
};

void flatten(model& mod, node& root)
{
    flatten_visitor visitor(mod);
    root.accept(visitor);
    mod.materials.push_back({}); // TODO
}

} // sg
} // visionaray
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2014-2015 Pavel Dolgov
 *
 * See the LICENSE file for terms of use.
 */

#ifndef CONSTANTS_HPP_
#define CONSTANTS_HPP_

namespace Gui {

/** The proportion of a number in a cell */
const double NUMBER_PROPORTION = 0.900000;

/** Maximum size of the game board to resize content */
const int RESIZE_MAX = 5;

/** Default size of the game board */
const int DEFAULT_SIZE = 10;

}

namespace Rules {

/** Minimum width/length of game board */
const int MIN_WIDTH = 3;

/** Maximum width/length of game board */
const int MAX_WIDTH = 16;

/** Default value for the time number */
const int DEFAULT_TIME = 30;

}

namespace Console {

/** Maximum length of indices */
const int MAX_INDEX_LENGTH = 2;

/** Minimal amount of spaces between numbers on the board */
const int NUMBER_OF_SPACES = 2;

}

#endif
<commit_msg>constants.hpp: new constant INDEX_FIELD<commit_after>/*
 * Copyright (C) 2014-2015 Pavel Dolgov
 *
 * See the LICENSE file for terms of use.
 */

#ifndef CONSTANTS_HPP_
#define CONSTANTS_HPP_

namespace Gui {

/** The proportion of a number in a cell */
const double NUMBER_PROPORTION = 0.900000;

/** Maximum size of the game board to resize content */
const int RESIZE_MAX = 5;

/** Default size of the game board */
const int DEFAULT_SIZE = 10;

}

namespace Rules {

/** Minimum width/length of game board */
const int MIN_WIDTH = 3;

/** Maximum width/length of game board */
const int MAX_WIDTH = 16;

/** Default value for the time number */
const int DEFAULT_TIME = 30;

}

namespace Console {

/** Field for indices and separator */
const int INDEX_FIELD = 5;

/** Maximum length of indices */
const int MAX_INDEX_LENGTH = 2;

/** Minimal amount of spaces between numbers on the board */
const int NUMBER_OF_SPACES = 2;

}

#endif
<|endoftext|>


<commit_before>#include "ui_mainwindow.h"
#include "converter.h"
#include "utilities.h"
#include "window.h"
#include <QTime>

Converter::Converter(QObject *parent) : QObject(parent) {
}

void Converter::start() {
    utils.addToLog("Starting conversion.");
    utils.killProcesses();

    utils.currentDuration = 0;

    QStringList arguments;
    arguments << "-y" << "-hide_banner";
    arguments << "-i" << utils.getCurrentRawFilename();

    if (!win.ui->cutFromEdit->text().trimmed().isEmpty() && !win.ui->cutToEdit->text().trimmed().isEmpty()) {
        arguments << "-ss" << win.ui->cutFromEdit->text().trimmed();
        arguments << "-to" << win.ui->cutToEdit->text().trimmed();
        utils.currentDuration = utils.getTrimmedVideoDuration();
    }

    if (win.ui->menuRemoveAudio->isChecked())
        arguments << "-an";

    arguments << utils.getCurrentFilename();

    utils.conversionProcess = new QProcess;
    utils.conversionProcess->setProcessChannelMode(QProcess::MergedChannels);
    utils.conversionProcess->start(utils.ffmpegBinaryName(), arguments);

    connect(utils.conversionProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(read()));
    connect(utils.conversionProcess, SIGNAL(finished(int)), this, SLOT(complete(int)));
}

void Converter::read() {
    QString buffer = utils.conversionProcess->readAllStandardOutput();
    QString duration, progress;
    QTime durationTime, progressTime;
    QRegExp time("\\d\\d\\:\\d\\d\\:\\d\\d\\.\\d\\d");
    time.indexIn(buffer);
    if (buffer.contains("Duration: ") && utils.currentDuration == 0) {
        duration = time.capturedTexts()[0];
        durationTime = QTime::fromString(duration, "hh:mm:ss.z");
        utils.currentDuration = QTime(0,0).secsTo(durationTime);
    } else {
        if (buffer != "") {
            progress = time.capturedTexts()[0];
            if (progress != "") {
                progressTime = QTime::fromString(progress, "hh:mm:ss.z");
                int percent = double((QTime(0,0).secsTo(progressTime)) / double(utils.currentDuration))*100;
                win.ui->conversionProgressBar->setValue(percent);
            }
        }
    }
    if (win.ui->menuFfmpegOutput->isChecked())
        utils.addToLog(buffer);
    else
        utils.addToLog(buffer, false);
}

void Converter::complete(int code) {
    utils.conversionProcess->deleteLater();
    utils.conversionProcess = NULL;
    win.updateConversionButton();

    if (utils.killed) {
        utils.addToLog("Conversion canceled.");
        utils.killed = false;
        win.toggleConversionButton();
        return;
    }
    if (code != 0) {
        utils.addToLog("Error on conversion. Check logs.");
        win.toggleConversionButton();
        return;
    }

    // In case video is so short that ffmpeg do not display
    // conversion status
    win.ui->conversionProgressBar->setValue(100);

    win.toggleConversionButton();
    win.updateConversionButton();

    if (win.ui->menuRemoveRawVideo->isChecked())
        utils.removeRawVideo();

    utils.addToLog("Conversion complete.");
    utils.addToLog("Saved to: " + utils.getCurrentFilename());

    if (win.ui->menuShowFile->isChecked())
        utils.showFileInDirectory();
}
<commit_msg>conversion progress bar is now more precise<commit_after>#include "ui_mainwindow.h"
#include "converter.h"
#include "utilities.h"
#include "window.h"
#include <QTime>

Converter::Converter(QObject *parent) : QObject(parent) {
}

void Converter::start() {
    utils.addToLog("Starting conversion.");
    utils.killProcesses();

    utils.currentDuration = 0;

    QStringList arguments;
    arguments << "-y" << "-hide_banner";
    arguments << "-i" << utils.getCurrentRawFilename();

    if (!win.ui->cutFromEdit->text().trimmed().isEmpty() && !win.ui->cutToEdit->text().trimmed().isEmpty()) {
        arguments << "-ss" << win.ui->cutFromEdit->text().trimmed();
        arguments << "-to" << win.ui->cutToEdit->text().trimmed();
        utils.currentDuration = utils.getTrimmedVideoDuration();
    }

    if (win.ui->menuRemoveAudio->isChecked())
        arguments << "-an";

    arguments << utils.getCurrentFilename();

    utils.conversionProcess = new QProcess;
    utils.conversionProcess->setProcessChannelMode(QProcess::MergedChannels);
    utils.conversionProcess->start(utils.ffmpegBinaryName(), arguments);

    connect(utils.conversionProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(read()));
    connect(utils.conversionProcess, SIGNAL(finished(int)), this, SLOT(complete(int)));
}

void Converter::read() {
    QString buffer = utils.conversionProcess->readAllStandardOutput();
    QString duration, progress;
    QTime durationTime, progressTime;
    QRegExp time("\\d\\d\\:\\d\\d\\:\\d\\d\\.\\d\\d");
    time.indexIn(buffer);
    if (buffer.contains("Duration: ") && utils.currentDuration == 0) {
        duration = time.capturedTexts()[0];
        durationTime = QTime::fromString(duration, "hh:mm:ss.z");
        utils.currentDuration = QTime(0,0).secsTo(durationTime);
    } else {
        if (buffer != "") {
            progress = time.capturedTexts()[0];
            if (progress != "") {
                progressTime = QTime::fromString(progress, "hh:mm:ss.z");
                int percent = double((QTime(0,0).msecsTo(progressTime)) / double(utils.currentDuration*1000))*100;
                win.ui->conversionProgressBar->setValue(percent);
            }
        }
    }
    if (win.ui->menuFfmpegOutput->isChecked())
        utils.addToLog(buffer);
    else
        utils.addToLog(buffer, false);
}

void Converter::complete(int code) {
    utils.conversionProcess->deleteLater();
    utils.conversionProcess = NULL;
    win.updateConversionButton();

    if (utils.killed) {
        utils.addToLog("Conversion canceled.");
        utils.killed = false;
        win.toggleConversionButton();
        return;
    }
    if (code != 0) {
        utils.addToLog("Error on conversion. Check logs.");
        win.toggleConversionButton();
        return;
    }

    // In case video is so short that ffmpeg do not display
    // conversion status
    win.ui->conversionProgressBar->setValue(100);

    win.toggleConversionButton();
    win.updateConversionButton();

    if (win.ui->menuRemoveRawVideo->isChecked())
        utils.removeRawVideo();

    utils.addToLog("Conversion complete.");
    utils.addToLog("Saved to: " + utils.getCurrentFilename());

    if (win.ui->menuShowFile->isChecked())
        utils.showFileInDirectory();
}
<|endoftext|>


<commit_before>/*
   Copyright (C) 2009-2010 Jack Poulson <jack.poulson@gmail.com>

   This file is part of Elemental.

   Elemental 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 3 of the License, or
   (at your option) any later version.

   Elemental 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 General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with Elemental.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "elemental/environment.hpp"
using namespace elemental;
using namespace std;

elemental::Grid::Grid
( MPI_Comm comm )
{
#ifndef RELEASE
    PushCallStack("Grid::Grid(comm)");
#endif

    // Extract the total number of processes
    MPI_Comm_size( comm, &_p );

    // Factor p
    int r = static_cast<int>(sqrt(static_cast<double>(_p)));
    while( _p % r != 0 )
        ++r;
    int c = _p / r;

    if( _p != r*c )
    {
        ostringstream msg;
        msg << "Number of processes must match grid size:" << endl
            << "  p=" << _p << ", (r,c)=(" << r << "," << c << ")" << endl;
        throw logic_error( msg.str() );
    }

    // Create cartesian communicator
    int dimensions[2] = { r,    c    };
    int periods[2]    = { true, true };
    int reorder       = false;
    MPI_Cart_create( comm, 2, dimensions, periods, reorder, &_comm );
    MPI_Comm_rank( _comm, &_rank  );

    Init( r, c );

#ifndef RELEASE
    PopCallStack();
#endif
}

// Currently forces a columnMajor absolute rank on the grid
elemental::Grid::Grid
( MPI_Comm comm, int r, int c )
{
#ifndef RELEASE
    PushCallStack("Grid::Grid( comm, r, c )");
#endif

    // Extract the total number of processes
    MPI_Comm_size( comm, &_p );

    if( _p != r*c )
    {
        ostringstream msg;
        msg << "Number of processes must match grid size:" << endl
            << "  p=" << _p << ", (r,c)=(" << r << "," << c << ")" << endl;
        throw logic_error( msg.str() );
    }

    // Create a cartesian communicator
    int dimensions[2] = { c, r };
    int periods[2]    = { true, true };
    int reorder       = false;
    MPI_Cart_create( comm, 2, dimensions, periods, reorder, &_comm );
    MPI_Comm_rank( _comm, &_rank );

    Init( r, c );

#ifndef RELEASE
    PopCallStack();
#endif
}

void
elemental::Grid::Init
( int r, int c )
{
#ifndef RELEASE
    PushCallStack("Grid::Init(r,c)");
    if( r <= 0 || c <= 0 )
        throw logic_error( "r and c must be positive." );
#endif
    _r = r;
    _c = c;

    _gcd = utilities::GCD( r, c );
    int lcm = _p / _gcd;

#ifndef RELEASE
    if( _rank == 0 )
    {
        cout << "Building process grid with:" << endl;
        cout << "  p=" << _p << ", (r,c)=(" << r << "," << c << ")" << endl;
        cout << "  gcd=" << _gcd << endl;
    }
#endif

    // Set up the MatrixCol and MatrixRow communicators
    int remainingDimensions[2];
    remainingDimensions[0] = false;
    remainingDimensions[1] = true;
    MPI_Cart_sub( _comm, remainingDimensions, &_matrixColComm );
    remainingDimensions[0] = true;
    remainingDimensions[1] = false;
    MPI_Cart_sub( _comm, remainingDimensions, &_matrixRowComm );
    MPI_Comm_rank( _matrixColComm, &_matrixColRank );
    MPI_Comm_rank( _matrixRowComm, &_matrixRowRank );

    // Set up the VectorCol and VectorRow communicators
    _vectorColRank = _matrixColRank + _r*_matrixRowRank;
    _vectorRowRank = _matrixRowRank + _c*_matrixColRank;
    MPI_Comm_split( _comm, 0, _vectorColRank, &_vectorColComm );
    MPI_Comm_split( _comm, 0, _vectorRowRank, &_vectorRowComm );

    // Compute which diagonal 'path' we're in, and what our rank is, then
    // perform AllGather world to store everyone's info
    _diagPathsAndRanks = new int[2*_p];
    int* myDiagPathAndRank = new int[2];
    myDiagPathAndRank[0] = (_matrixRowRank+r-_matrixColRank) % _gcd;
    int diagPathRank = 0;
    int row = 0;
    int col = myDiagPathAndRank[0];
    for( int j=0; j<lcm; ++j )
    {
        if( row == _matrixColRank && col == _matrixRowRank )
        {
            myDiagPathAndRank[1] = diagPathRank;
            break;
        }
        else
        {
            row = (row + 1) % r;
            col = (col + 1) % c;
            ++diagPathRank;
        }
    }
    wrappers::mpi::AllGather
    ( myDiagPathAndRank, 2, _diagPathsAndRanks, 2, _vectorColComm );
    delete[] myDiagPathAndRank;

#ifndef RELEASE
    MPI_Errhandler_set( _matrixColComm, MPI_ERRORS_RETURN );
    MPI_Errhandler_set( _matrixRowComm, MPI_ERRORS_RETURN );
    MPI_Errhandler_set( _vectorColComm, MPI_ERRORS_RETURN );
    MPI_Errhandler_set( _vectorRowComm, MPI_ERRORS_RETURN );
#endif

#ifndef RELEASE
    PopCallStack();
#endif
}

<commit_msg>Fixed ordering of Cartesian communicator when no grid dimensions were specified.<commit_after>/*
   Copyright (C) 2009-2010 Jack Poulson <jack.poulson@gmail.com>

   This file is part of Elemental.

   Elemental 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 3 of the License, or
   (at your option) any later version.

   Elemental 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 General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with Elemental.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "elemental/environment.hpp"
using namespace elemental;
using namespace std;

elemental::Grid::Grid
( MPI_Comm comm )
{
#ifndef RELEASE
    PushCallStack("Grid::Grid(comm)");
#endif

    // Extract the total number of processes
    MPI_Comm_size( comm, &_p );

    // Factor p
    int r = static_cast<int>(sqrt(static_cast<double>(_p)));
    while( _p % r != 0 )
        ++r;
    int c = _p / r;

    if( _p != r*c )
    {
        ostringstream msg;
        msg << "Number of processes must match grid size:" << endl
            << "  p=" << _p << ", (r,c)=(" << r << "," << c << ")" << endl;
        throw logic_error( msg.str() );
    }

    // Create cartesian communicator
    int dimensions[2] = { c, r };
    int periods[2] = { true, true };
    int reorder = false;
    MPI_Cart_create( comm, 2, dimensions, periods, reorder, &_comm );
    MPI_Comm_rank( _comm, &_rank  );

    Init( r, c );

#ifndef RELEASE
    PopCallStack();
#endif
}

// Currently forces a columnMajor absolute rank on the grid
elemental::Grid::Grid
( MPI_Comm comm, int r, int c )
{
#ifndef RELEASE
    PushCallStack("Grid::Grid( comm, r, c )");
#endif

    // Extract the total number of processes
    MPI_Comm_size( comm, &_p );

    if( _p != r*c )
    {
        ostringstream msg;
        msg << "Number of processes must match grid size:" << endl
            << "  p=" << _p << ", (r,c)=(" << r << "," << c << ")" << endl;
        throw logic_error( msg.str() );
    }

    // Create a cartesian communicator
    int dimensions[2] = { c, r };
    int periods[2] = { true, true };
    int reorder = false;
    MPI_Cart_create( comm, 2, dimensions, periods, reorder, &_comm );
    MPI_Comm_rank( _comm, &_rank );

    Init( r, c );

#ifndef RELEASE
    PopCallStack();
#endif
}

void
elemental::Grid::Init
( int r, int c )
{
#ifndef RELEASE
    PushCallStack("Grid::Init(r,c)");
    if( r <= 0 || c <= 0 )
        throw logic_error( "r and c must be positive." );
#endif
    _r = r;
    _c = c;

    _gcd = utilities::GCD( r, c );
    int lcm = _p / _gcd;

#ifndef RELEASE
    if( _rank == 0 )
    {
        cout << "Building process grid with:" << endl;
        cout << "  p=" << _p << ", (r,c)=(" << r << "," << c << ")" << endl;
        cout << "  gcd=" << _gcd << endl;
    }
#endif

    // Set up the MatrixCol and MatrixRow communicators
    int remainingDimensions[2];
    remainingDimensions[0] = false;
    remainingDimensions[1] = true;
    MPI_Cart_sub( _comm, remainingDimensions, &_matrixColComm );
    remainingDimensions[0] = true;
    remainingDimensions[1] = false;
    MPI_Cart_sub( _comm, remainingDimensions, &_matrixRowComm );
    MPI_Comm_rank( _matrixColComm, &_matrixColRank );
    MPI_Comm_rank( _matrixRowComm, &_matrixRowRank );

    // Set up the VectorCol and VectorRow communicators
    _vectorColRank = _matrixColRank + _r*_matrixRowRank;
    _vectorRowRank = _matrixRowRank + _c*_matrixColRank;
    MPI_Comm_split( _comm, 0, _vectorColRank, &_vectorColComm );
    MPI_Comm_split( _comm, 0, _vectorRowRank, &_vectorRowComm );

    // Compute which diagonal 'path' we're in, and what our rank is, then
    // perform AllGather world to store everyone's info
    _diagPathsAndRanks = new int[2*_p];
    int* myDiagPathAndRank = new int[2];
    myDiagPathAndRank[0] = (_matrixRowRank+r-_matrixColRank) % _gcd;
    int diagPathRank = 0;
    int row = 0;
    int col = myDiagPathAndRank[0];
    for( int j=0; j<lcm; ++j )
    {
        if( row == _matrixColRank && col == _matrixRowRank )
        {
            myDiagPathAndRank[1] = diagPathRank;
            break;
        }
        else
        {
            row = (row + 1) % r;
            col = (col + 1) % c;
            ++diagPathRank;
        }
    }
    wrappers::mpi::AllGather
    ( myDiagPathAndRank, 2, _diagPathsAndRanks, 2, _vectorColComm );
    delete[] myDiagPathAndRank;

#ifndef RELEASE
    MPI_Errhandler_set( _matrixColComm, MPI_ERRORS_RETURN );
    MPI_Errhandler_set( _matrixRowComm, MPI_ERRORS_RETURN );
    MPI_Errhandler_set( _vectorColComm, MPI_ERRORS_RETURN );
    MPI_Errhandler_set( _vectorRowComm, MPI_ERRORS_RETURN );
#endif

#ifndef RELEASE
    PopCallStack();
#endif
}

<|endoftext|>


<commit_before>/**
 This file is part of Deformable Shape Tracking (DEST).

 Copyright Christoph Heindl 2015

 Deformable Shape Tracking 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 3 of the License, or
 (at your option) any later version.

 Deformable Shape Tracking 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 General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with Deformable Shape Tracking. If not, see <http://www.gnu.org/licenses/>.
 */

#include <dest/core/tree.h>
#include <dest/util/log.h>
#include <dest/io/matrix_io.h>
#include <queue>

namespace dest {
    namespace core {

        struct Tree::SplitInfo {
            int idx1;
            int idx2;
            float threshold;
        };

        struct Tree::TreeNode {
            // For intermediate nodes
            Tree::SplitInfo split;
            // For leaf nodes
            ShapeResidual mean;

            flatbuffers::Offset<io::TreeNode> save(flatbuffers::FlatBufferBuilder &fbb) const {
                flatbuffers::Offset<io::MatrixF> lmean = io::toFbs(fbb, mean);
                return io::CreateTreeNode(fbb, split.idx1, split.idx2, split.threshold, lmean);
            }

            void load(const io::TreeNode &fbs) {
                split.idx1 = fbs.idx1();
                split.idx2 = fbs.idx2();
                split.threshold = fbs.threshold();
                io::fromFbs(*fbs.mean(), mean);
            }
        };

        typedef std::pair<TreeTraining::SampleVector::iterator, TreeTraining::SampleVector::iterator> SampleRange;

        struct Tree::NodeInfo {
            int node;
            int depth;
            SampleRange range;

            NodeInfo() {}

            NodeInfo(int n, int d, const SampleRange &r)
            :node(n), depth(d)
            {
                range.first = r.first;
                range.second = r.second;
            }

            NodeInfo(const NodeInfo &other)
                :node(other.node), depth(other.depth)
            {
                range.first = other.range.first;
                range.second = other.range.second;
            }
        };

        inline int numElementsInRange(const SampleRange &r) {
            return static_cast<int>(std::distance(r.first, r.second));
        }

        inline ShapeResidual meanResidualOfRange(const SampleRange &r, int numLandmarks) {
            ShapeResidual mean = ShapeResidual::Zero(2, numLandmarks);

            const int numElements = numElementsInRange(r);
            if (numElements > 0) {
                for (TreeTraining::SampleVector::iterator i = r.first; i != r.second; ++i) {
                    mean += i->residual;
                }
                mean /= static_cast<float>(numElements);
            }
            return mean;
        }

        template<class UnaryPredicate>
        inline std::pair<ShapeResidual, int> meanResidualOfRangeIf(const SampleRange &r, int numLandmarks, UnaryPredicate pred) {
            ShapeResidual mean = ShapeResidual::Zero(2, numLandmarks);

            int numElements = 0;
            for (TreeTraining::SampleVector::iterator i = r.first; i != r.second; ++i) {
                if (pred(*i)) {
                    mean += i->residual;
                    ++numElements;
                }
            }
            if (numElements > 0) {
                mean /= static_cast<float>(numElements);
            }

            return std::make_pair(mean, numElements);
        }

        struct Tree::data {

            std::vector<Tree::TreeNode> nodes;
            int depth;

            data()
            : depth(0)
            {}

            flatbuffers::Offset<io::Tree> save(flatbuffers::FlatBufferBuilder &fbb) const {
                std::vector<flatbuffers::Offset<io::TreeNode> > nlocs;

                for (size_t i = 0; i < nodes.size(); ++i) {
                    nlocs.push_back(nodes[i].save(fbb));
                }

                return io::CreateTree(fbb, fbb.CreateVector(nlocs), depth);
            }

            void load(const io::Tree &fbs) {
                depth = fbs.depth();

                nodes.resize(fbs.nodes()->size());
                for (flatbuffers::uoffset_t i = 0; i < fbs.nodes()->size(); ++i) {
                    nodes[i].load(*fbs.nodes()->Get(i));
                }
            }
        };

        Tree::Tree()
        : _data(new data())
        {}

        Tree::Tree(const Tree &other)
        : _data(new data(*other._data))
        {}

        Tree::~Tree()
        {}

        flatbuffers::Offset<io::Tree> Tree::save(flatbuffers::FlatBufferBuilder &fbb) const {
            return _data->save(fbb);
        }

        void Tree::load(const io::Tree &fbs) {
            _data->load(fbs);
        }

        bool Tree::fit(TreeTraining &t)
        {
            std::vector<Tree::TreeNode> &nodes = _data->nodes;
            int &depth = _data->depth;

            depth = std::max<int>(t.trainingData->params.maxTreeDepth, 1);
            const int numNodes = (int)std::pow(2.0, depth) - 1;
            nodes.resize(numNodes);

            // Split recursively in BFS
            std::queue<NodeInfo> queue;
            queue.push(NodeInfo(0, 1, std::make_pair(t.samples.begin(), t.samples.end())));

            while (!queue.empty()) {
                const NodeInfo nr = queue.front(); queue.pop();

                if (nr.depth < depth) {
                    // Generate a split
                    NodeInfo left, right;
                    if (splitNode(t, nr, left, right)) {
                        queue.push(left);
                        queue.push(right);
                    } else {
                        makeLeaf(t, nr);
                    }

                } else {
                    makeLeaf(t, nr);
                }
            }

            return true;
        }

        struct Tree::PartitionPredicate {
            SplitInfo split;

            bool operator()(const TreeTraining::Sample &s) const {
                return (s.intensities(split.idx1) - s.intensities(split.idx2)) > split.threshold;
            }

        };

        bool Tree::splitNode(TreeTraining &t, const NodeInfo &parent, NodeInfo &left, NodeInfo &right) {

            const bool emptyRange = parent.range.second == parent.range.first;
            if (emptyRange) {
                // Premature leaf
                return false;
            }

            // Generate random split positions
            std::vector<SplitInfo> splits;
            sampleSplitPositions(t, splits);

            const ShapeResidual meanResidualParent = meanResidualOfRange(parent.range, t.numLandmarks);

            // Choose best split according to minimization of residual energy
            float maxEnergy = -std::numeric_limits<float>::max();
            size_t bestSplit = std::numeric_limits<size_t>::max();

            for (size_t i = 0; i < splits.size(); ++i) {
                float e = splitEnergy(t, parent, meanResidualParent, splits[i]);
                if (e > maxEnergy) {
                    maxEnergy = e;
                    bestSplit = i;
                }
            }

            if (maxEnergy == -std::numeric_limits<float>::max()) {
                return false;
            }

            TreeNode &parentNode = _data->nodes[parent.node];
            parentNode.split = splits[bestSplit];

            PartitionPredicate pred;
            pred.split = splits[bestSplit];
            TreeTraining::SampleVector::iterator middle = std::partition(parent.range.first, parent.range.second, pred);

            if (middle == parent.range.first || middle == parent.range.second) {
                return false;
            }

            left.node = parent.node * 2 + 1;
            right.node = parent.node * 2 + 2;
            left.depth = right.depth = parent.depth + 1;
            left.range = SampleRange(parent.range.first, middle);
            right.range = SampleRange(middle, parent.range.second);

            return true;
        }

        void Tree::makeLeaf(TreeTraining &t, const NodeInfo &ni) {

            Tree::TreeNode &leaf = _data->nodes[ni.node];
            leaf.split.idx1 = -1;
            leaf.split.idx2 = -1;
            leaf.mean = meanResidualOfRange(ni.range, t.numLandmarks);
        }

        void Tree::sampleSplitPositions(TreeTraining &t, std::vector<SplitInfo> &splits) const
        {
            splits.clear();

            const int maxAttempts = 100;
            std::uniform_int_distribution<int> di(0, static_cast<int>(t.pixelCoordinates.cols()) - 1);
            std::uniform_real_distribution<float> drZeroOne(0.f, 1.f);
            std::uniform_real_distribution<float> drThreshold(-255.f, 255.f);

            const int numTests = t.trainingData->params.numRandomSplitTestsPerNode;
            const float invlambda = 1.f / t.trainingData->params.exponentialLambda;

            for (int i = 0; i < numTests; ++i) {

                SplitInfo split;
                int iter = 0;
                float e;
                do {
                    split.idx1 = di(t.trainingData->rnd);
                    split.idx2 = di(t.trainingData->rnd);
                    float d = (t.pixelCoordinates.col(split.idx1) - t.pixelCoordinates.col(split.idx2)).norm();
                    e = std::exp(-d * invlambda); // Note, shapes live in normalized space,  therefore rather divide by lambda.
                    ++iter;

                } while (iter <= maxAttempts && split.idx1 == split.idx2 && (drZeroOne(t.trainingData->rnd) < e));

                if (iter <= maxAttempts) {
                    split.threshold = drThreshold(t.trainingData->rnd);
                    splits.push_back(split);
                }
            }
        }

        float Tree::splitEnergy(TreeTraining &t, const NodeInfo &parent, const ShapeResidual &parentMeanResidual, const SplitInfo &split) const {

            PartitionPredicate pred;
            pred.split = split;

            std::pair<ShapeResidual, int> left = meanResidualOfRangeIf(parent.range, t.numLandmarks, pred);

            const float numLeft = static_cast<float>(left.second);
            const float numParent = static_cast<float>(numElementsInRange(parent.range));
            const float numRight = numParent - numLeft;

            ShapeResidual rRight = (numParent * parentMeanResidual - numLeft * left.first) / numRight;

            return left.second * left.first.squaredNorm() + numRight * rRight.squaredNorm();
        }

        ShapeResidual Tree::predict(const PixelIntensities &intensities) const
        {
            const TreeNode *nodes = &_data->nodes[0];

            const int maxTests = _data->depth - 1;

            int n = 0;
            for (int i = 0; i < maxTests; ++i) {
                const TreeNode &node = nodes[n];

                if (node.split.idx1 < 0)
                    break; // premature leaf

                bool left = intensities(node.split.idx1) - intensities(node.split.idx2) > node.split.threshold;

                n = left ? 2 * n + 1 : 2 * n + 2;
            }

            return nodes[n].mean;
        }

    }
}<commit_msg>Favor closer pairs.<commit_after>/**
 This file is part of Deformable Shape Tracking (DEST).

 Copyright Christoph Heindl 2015

 Deformable Shape Tracking 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 3 of the License, or
 (at your option) any later version.

 Deformable Shape Tracking 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 General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with Deformable Shape Tracking. If not, see <http://www.gnu.org/licenses/>.
 */

#include <dest/core/tree.h>
#include <dest/util/log.h>
#include <dest/io/matrix_io.h>
#include <queue>

namespace dest {
    namespace core {

        struct Tree::SplitInfo {
            int idx1;
            int idx2;
            float threshold;
        };

        struct Tree::TreeNode {
            // For intermediate nodes
            Tree::SplitInfo split;
            // For leaf nodes
            ShapeResidual mean;

            flatbuffers::Offset<io::TreeNode> save(flatbuffers::FlatBufferBuilder &fbb) const {
                flatbuffers::Offset<io::MatrixF> lmean = io::toFbs(fbb, mean);
                return io::CreateTreeNode(fbb, split.idx1, split.idx2, split.threshold, lmean);
            }

            void load(const io::TreeNode &fbs) {
                split.idx1 = fbs.idx1();
                split.idx2 = fbs.idx2();
                split.threshold = fbs.threshold();
                io::fromFbs(*fbs.mean(), mean);
            }
        };

        typedef std::pair<TreeTraining::SampleVector::iterator, TreeTraining::SampleVector::iterator> SampleRange;

        struct Tree::NodeInfo {
            int node;
            int depth;
            SampleRange range;

            NodeInfo() {}

            NodeInfo(int n, int d, const SampleRange &r)
            :node(n), depth(d)
            {
                range.first = r.first;
                range.second = r.second;
            }

            NodeInfo(const NodeInfo &other)
                :node(other.node), depth(other.depth)
            {
                range.first = other.range.first;
                range.second = other.range.second;
            }
        };

        inline int numElementsInRange(const SampleRange &r) {
            return static_cast<int>(std::distance(r.first, r.second));
        }

        inline ShapeResidual meanResidualOfRange(const SampleRange &r, int numLandmarks) {
            ShapeResidual mean = ShapeResidual::Zero(2, numLandmarks);

            const int numElements = numElementsInRange(r);
            if (numElements > 0) {
                for (TreeTraining::SampleVector::iterator i = r.first; i != r.second; ++i) {
                    mean += i->residual;
                }
                mean /= static_cast<float>(numElements);
            }
            return mean;
        }

        template<class UnaryPredicate>
        inline std::pair<ShapeResidual, int> meanResidualOfRangeIf(const SampleRange &r, int numLandmarks, UnaryPredicate pred) {
            ShapeResidual mean = ShapeResidual::Zero(2, numLandmarks);

            int numElements = 0;
            for (TreeTraining::SampleVector::iterator i = r.first; i != r.second; ++i) {
                if (pred(*i)) {
                    mean += i->residual;
                    ++numElements;
                }
            }
            if (numElements > 0) {
                mean /= static_cast<float>(numElements);
            }

            return std::make_pair(mean, numElements);
        }

        struct Tree::data {

            std::vector<Tree::TreeNode> nodes;
            int depth;

            data()
            : depth(0)
            {}

            flatbuffers::Offset<io::Tree> save(flatbuffers::FlatBufferBuilder &fbb) const {
                std::vector<flatbuffers::Offset<io::TreeNode> > nlocs;

                for (size_t i = 0; i < nodes.size(); ++i) {
                    nlocs.push_back(nodes[i].save(fbb));
                }

                return io::CreateTree(fbb, fbb.CreateVector(nlocs), depth);
            }

            void load(const io::Tree &fbs) {
                depth = fbs.depth();

                nodes.resize(fbs.nodes()->size());
                for (flatbuffers::uoffset_t i = 0; i < fbs.nodes()->size(); ++i) {
                    nodes[i].load(*fbs.nodes()->Get(i));
                }
            }
        };

        Tree::Tree()
        : _data(new data())
        {}

        Tree::Tree(const Tree &other)
        : _data(new data(*other._data))
        {}

        Tree::~Tree()
        {}

        flatbuffers::Offset<io::Tree> Tree::save(flatbuffers::FlatBufferBuilder &fbb) const {
            return _data->save(fbb);
        }

        void Tree::load(const io::Tree &fbs) {
            _data->load(fbs);
        }

        bool Tree::fit(TreeTraining &t)
        {
            std::vector<Tree::TreeNode> &nodes = _data->nodes;
            int &depth = _data->depth;

            depth = std::max<int>(t.trainingData->params.maxTreeDepth, 1);
            const int numNodes = (int)std::pow(2.0, depth) - 1;
            nodes.resize(numNodes);

            // Split recursively in BFS
            std::queue<NodeInfo> queue;
            queue.push(NodeInfo(0, 1, std::make_pair(t.samples.begin(), t.samples.end())));

            while (!queue.empty()) {
                const NodeInfo nr = queue.front(); queue.pop();

                if (nr.depth < depth) {
                    // Generate a split
                    NodeInfo left, right;
                    if (splitNode(t, nr, left, right)) {
                        queue.push(left);
                        queue.push(right);
                    } else {
                        makeLeaf(t, nr);
                    }

                } else {
                    makeLeaf(t, nr);
                }
            }

            return true;
        }

        struct Tree::PartitionPredicate {
            SplitInfo split;

            bool operator()(const TreeTraining::Sample &s) const {
                return (s.intensities(split.idx1) - s.intensities(split.idx2)) > split.threshold;
            }

        };

        bool Tree::splitNode(TreeTraining &t, const NodeInfo &parent, NodeInfo &left, NodeInfo &right) {

            const bool emptyRange = parent.range.second == parent.range.first;
            if (emptyRange) {
                // Premature leaf
                return false;
            }

            // Generate random split positions
            std::vector<SplitInfo> splits;
            sampleSplitPositions(t, splits);

            const ShapeResidual meanResidualParent = meanResidualOfRange(parent.range, t.numLandmarks);

            // Choose best split according to minimization of residual energy
            float maxEnergy = -std::numeric_limits<float>::max();
            size_t bestSplit = std::numeric_limits<size_t>::max();

            for (size_t i = 0; i < splits.size(); ++i) {
                float e = splitEnergy(t, parent, meanResidualParent, splits[i]);
                if (e > maxEnergy) {
                    maxEnergy = e;
                    bestSplit = i;
                }
            }

            if (maxEnergy == -std::numeric_limits<float>::max()) {
                return false;
            }

            TreeNode &parentNode = _data->nodes[parent.node];
            parentNode.split = splits[bestSplit];

            PartitionPredicate pred;
            pred.split = splits[bestSplit];
            TreeTraining::SampleVector::iterator middle = std::partition(parent.range.first, parent.range.second, pred);

            if (middle == parent.range.first || middle == parent.range.second) {
                return false;
            }

            left.node = parent.node * 2 + 1;
            right.node = parent.node * 2 + 2;
            left.depth = right.depth = parent.depth + 1;
            left.range = SampleRange(parent.range.first, middle);
            right.range = SampleRange(middle, parent.range.second);

            return true;
        }

        void Tree::makeLeaf(TreeTraining &t, const NodeInfo &ni) {

            Tree::TreeNode &leaf = _data->nodes[ni.node];
            leaf.split.idx1 = -1;
            leaf.split.idx2 = -1;
            leaf.mean = meanResidualOfRange(ni.range, t.numLandmarks);
        }

        void Tree::sampleSplitPositions(TreeTraining &t, std::vector<SplitInfo> &splits) const
        {
            splits.clear();

            const int maxAttempts = 100;
            std::uniform_int_distribution<int> di(0, static_cast<int>(t.pixelCoordinates.cols()) - 1);
            std::uniform_real_distribution<float> drZeroOne(0.f, 1.f);
            std::uniform_real_distribution<float> drThreshold(-255.f, 255.f);

            const int numTests = t.trainingData->params.numRandomSplitTestsPerNode;
            const float invlambda = 1.f / t.trainingData->params.exponentialLambda;

            for (int i = 0; i < numTests; ++i) {

                SplitInfo split;
                int iter = 0;
                float e;
                do {
                    split.idx1 = di(t.trainingData->rnd);
                    split.idx2 = di(t.trainingData->rnd);
                    float d = (t.pixelCoordinates.col(split.idx1) - t.pixelCoordinates.col(split.idx2)).norm();
                    e = std::exp(-d * invlambda); // Note, shapes live in normalized space,  therefore rather divide by lambda.
                    ++iter;

                } while (iter <= maxAttempts && split.idx1 == split.idx2 && (drZeroOne(t.trainingData->rnd) >= e));

                if (iter <= maxAttempts) {
                    split.threshold = drThreshold(t.trainingData->rnd);
                    splits.push_back(split);
                }
            }
        }

        float Tree::splitEnergy(TreeTraining &t, const NodeInfo &parent, const ShapeResidual &parentMeanResidual, const SplitInfo &split) const {

            PartitionPredicate pred;
            pred.split = split;

            std::pair<ShapeResidual, int> left = meanResidualOfRangeIf(parent.range, t.numLandmarks, pred);

            const float numLeft = static_cast<float>(left.second);
            const float numParent = static_cast<float>(numElementsInRange(parent.range));
            const float numRight = numParent - numLeft;

            ShapeResidual rRight = (numParent * parentMeanResidual - numLeft * left.first) / numRight;

            return left.second * left.first.squaredNorm() + numRight * rRight.squaredNorm();
        }

        ShapeResidual Tree::predict(const PixelIntensities &intensities) const
        {
            const TreeNode *nodes = &_data->nodes[0];

            const int maxTests = _data->depth - 1;

            int n = 0;
            for (int i = 0; i < maxTests; ++i) {
                const TreeNode &node = nodes[n];

                if (node.split.idx1 < 0)
                    break; // premature leaf

                bool left = intensities(node.split.idx1) - intensities(node.split.idx2) > node.split.threshold;

                n = left ? 2 * n + 1 : 2 * n + 2;
            }

            return nodes[n].mean;
        }

    }
}<|endoftext|>


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

#include "core_io.h"

#include "primitives/block.h"
#include "primitives/transaction.h"
#include "script/script.h"
#include "serialize.h"
#include "streams.h"
#include <univalue.h>
#include "util.h"
#include "utilstrencodings.h"
#include "version.h"

#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/assign/list_of.hpp>

using namespace std;

CScript ParseScript(std::string s)
{
    CScript result;

    static map<string, opcodetype> mapOpNames;

    if (mapOpNames.empty())
    {
        for (int op = 0; op < FIRST_UNDEFINED_OP_VALUE; op++)
        {
            // ignore all "PUSHDATA" ops, but dont ignore OP_RESERVED
            if (op < OP_NOP && op != OP_RESERVED)
                continue;

            const char* name = GetOpName((opcodetype)op);
            if (strcmp(name, "OP_UNKNOWN") == 0)
                continue;
            string strName(name);
            mapOpNames[strName] = (opcodetype)op;
            // Convenience: OP_ADD and just ADD are both recognized:
            boost::algorithm::replace_first(strName, "OP_", "");
            mapOpNames[strName] = (opcodetype)op;
        }
    }

    vector<string> words;
    boost::algorithm::split(words, s, boost::algorithm::is_any_of(" \t\n"), boost::algorithm::token_compress_on);

    for (std::vector<std::string>::const_iterator w = words.begin(); w != words.end(); ++w)
    {
        if (w->empty())
        {
            // Empty string, ignore. (boost::split given '' will return one word)
        }
        else if (all(*w, boost::algorithm::is_digit()) ||
            (boost::algorithm::starts_with(*w, "-") && all(string(w->begin()+1, w->end()), boost::algorithm::is_digit())))
        {
            // Number
            int64_t n = atoi64(*w);
            result << n;
        } else if (boost::algorithm::starts_with(*w, "0x") &&
                   (w->begin() + 2 != w->end())) {
            if (IsHex(std::string(w->begin() + 2, w->end()))) {
                // Raw hex data, inserted NOT pushed onto stack:
                std::vector<uint8_t> raw =
                    ParseHex(std::string(w->begin() + 2, w->end()));
                result.insert(result.end(), raw.begin(), raw.end());
            } else {
                // Should only arrive here for improperly formatted hex values
                throw std::runtime_error("Hex numbers expected to be formatted "
                                         "in full-byte chunks (ex: 0x00 "
                                         "instead of 0x0)");
            }
        } else if (w->size() >= 2 && boost::algorithm::starts_with(*w, "'") &&
                   boost::algorithm::ends_with(*w, "'")) {
            // Single-quoted string, pushed as data. NOTE: this is poor-man's
            // parsing, spaces/tabs/newlines in single-quoted strings won't work.
            std::vector<unsigned char> value(w->begin()+1, w->end()-1);
            result << value;
        }
        else if (mapOpNames.count(*w))
        {
            // opcode, e.g. OP_ADD or ADD:
            result << mapOpNames[*w];
        } else {
            throw std::runtime_error("Error parsing script: " + s);
        }
    }

    return result;
}

bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx)
{
    if (!IsHex(strHexTx))
        return false;

    vector<unsigned char> txData(ParseHex(strHexTx));
    CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
    try {
        ssData >> tx;
        if (!ssData.empty())
            return false;
    }
    catch (const std::exception&) {
        return false;
    }

    return true;
}

bool DecodeHexBlk(CBlock& block, const std::string& strHexBlk)
{
    if (!IsHex(strHexBlk))
        return false;

    std::vector<unsigned char> blockData(ParseHex(strHexBlk));
    CDataStream ssBlock(blockData, SER_NETWORK, PROTOCOL_VERSION);
    try {
        ssBlock >> block;
    }
    catch (const std::exception&) {
        return false;
    }

    return true;
}

uint256 ParseHashUV(const UniValue& v, const string& strName)
{
    string strHex;
    if (v.isStr())
        strHex = v.getValStr();
    return ParseHashStr(strHex, strName);  // Note: ParseHashStr("") throws a runtime_error
}

uint256 ParseHashStr(const std::string& strHex, const std::string& strName)
{
    if (!IsHex(strHex)) // Note: IsHex("") is false
        throw runtime_error(strName+" must be hexadecimal string (not '"+strHex+"')");

    uint256 result;
    result.SetHex(strHex);
    return result;
}

vector<unsigned char> ParseHexUV(const UniValue& v, const string& strName)
{
    string strHex;
    if (v.isStr())
        strHex = v.getValStr();
    if (!IsHex(strHex))
        throw runtime_error(strName+" must be hexadecimal string (not '"+strHex+"')");
    return ParseHex(strHex);
}
<commit_msg>Refactor ParseScript logic to remove `else` conditions<commit_after>// Copyright (c) 2009-2014 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "core_io.h"

#include "primitives/block.h"
#include "primitives/transaction.h"
#include "script/script.h"
#include "serialize.h"
#include "streams.h"
#include <univalue.h>
#include "util.h"
#include "utilstrencodings.h"
#include "version.h"

#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/assign/list_of.hpp>

using namespace std;

CScript ParseScript(std::string s)
{
    CScript result;

    static map<string, opcodetype> mapOpNames;

    if (mapOpNames.empty())
    {
        for (int op = 0; op < FIRST_UNDEFINED_OP_VALUE; op++)
        {
            // ignore all "PUSHDATA" ops, but dont ignore OP_RESERVED
            if (op < OP_NOP && op != OP_RESERVED)
                continue;

            const char* name = GetOpName((opcodetype)op);
            if (strcmp(name, "OP_UNKNOWN") == 0)
                continue;
            string strName(name);
            mapOpNames[strName] = (opcodetype)op;
            // Convenience: OP_ADD and just ADD are both recognized:
            boost::algorithm::replace_first(strName, "OP_", "");
            mapOpNames[strName] = (opcodetype)op;
        }
    }

    std::vector<std::string> words;
    boost::algorithm::split(words, s, boost::algorithm::is_any_of(" \t\n"),
                            boost::algorithm::token_compress_on);

    for (const auto &w : words) {
        if (w.empty()) {
            // Empty string, ignore. (boost::split given '' will return one
            // word)
            continue;
        }

        if (all(w, boost::algorithm::is_digit()) ||
            (boost::algorithm::starts_with(w, "-") &&
             all(std::string(w.begin() + 1, w.end()),
                 boost::algorithm::is_digit()))) {
            // Number
            int64_t n = atoi64(w);
            result << n;
            continue;
        }

        if (boost::algorithm::starts_with(w, "0x") &&
            (w.begin() + 2 != w.end())) {
            if (!IsHex(std::string(w.begin() + 2, w.end()))) {
                // Should only arrive here for improperly formatted hex values
                throw std::runtime_error("Hex numbers expected to be formatted "
                                         "in full-byte chunks (ex: 0x00 "
                                         "instead of 0x0)");
            }

            // Raw hex data, inserted NOT pushed onto stack:
            std::vector<uint8_t> raw =
                ParseHex(std::string(w.begin() + 2, w.end()));
            result.insert(result.end(), raw.begin(), raw.end());
            continue;
        }

        if (w.size() >= 2 && boost::algorithm::starts_with(w, "'") &&
            boost::algorithm::ends_with(w, "'")) {
            // Single-quoted string, pushed as data. NOTE: this is poor-man's
            // parsing, spaces/tabs/newlines in single-quoted strings won't
            // work.
            std::vector<uint8_t> value(w.begin() + 1, w.end() - 1);
            result << value;
            continue;
        }

        if (mapOpNames.count(w)) {
            // opcode, e.g. OP_ADD or ADD:
            result << mapOpNames[w];
            continue;
        }

        throw std::runtime_error("Error parsing script: " + s);
    }

    return result;
}

bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx)
{
    if (!IsHex(strHexTx))
        return false;

    vector<unsigned char> txData(ParseHex(strHexTx));
    CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
    try {
        ssData >> tx;
        if (!ssData.empty())
            return false;
    }
    catch (const std::exception&) {
        return false;
    }

    return true;
}

bool DecodeHexBlk(CBlock& block, const std::string& strHexBlk)
{
    if (!IsHex(strHexBlk))
        return false;

    std::vector<unsigned char> blockData(ParseHex(strHexBlk));
    CDataStream ssBlock(blockData, SER_NETWORK, PROTOCOL_VERSION);
    try {
        ssBlock >> block;
    }
    catch (const std::exception&) {
        return false;
    }

    return true;
}

uint256 ParseHashUV(const UniValue& v, const string& strName)
{
    string strHex;
    if (v.isStr())
        strHex = v.getValStr();
    return ParseHashStr(strHex, strName);  // Note: ParseHashStr("") throws a runtime_error
}

uint256 ParseHashStr(const std::string& strHex, const std::string& strName)
{
    if (!IsHex(strHex)) // Note: IsHex("") is false
        throw runtime_error(strName+" must be hexadecimal string (not '"+strHex+"')");

    uint256 result;
    result.SetHex(strHex);
    return result;
}

vector<unsigned char> ParseHexUV(const UniValue& v, const string& strName)
{
    string strHex;
    if (v.isStr())
        strHex = v.getValStr();
    if (!IsHex(strHex))
        throw runtime_error(strName+" must be hexadecimal string (not '"+strHex+"')");
    return ParseHex(strHex);
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2013 Jolla Ltd.
** Contact: Petri M. Gerdt <petri.gerdt@jollamobile.com>
**
****************************************************************************/

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "dbmanager.h"

#include <QMetaObject>

#include "dbworker.h"

static DBManager *gDbManager = 0;

DBManager *DBManager::instance()
{
    if (!gDbManager) {
        gDbManager = new DBManager();
    }
    return gDbManager;
}

DBManager::DBManager(QObject *parent)
    : QObject(parent)
    , m_maxTabId(0)
{
    qRegisterMetaType<QList<Tab> >("QList<Tab>");
    qRegisterMetaType<QList<Link> >("QList<Link>");
    qRegisterMetaType<Tab>("Tab");

    worker = new DBWorker();
    worker->moveToThread(&workerThread);

    connect(&workerThread, SIGNAL(finished()), worker, SLOT(deleteLater()));
    connect(worker, SIGNAL(tabsAvailable(QList<Tab>)), this, SLOT(tabListAvailable(QList<Tab>)));
    connect(worker, SIGNAL(historyAvailable(QList<Link>)), this, SIGNAL(historyAvailable(QList<Link>)));
    connect(worker, SIGNAL(tabHistoryAvailable(int,QList<Link>)), this, SIGNAL(tabHistoryAvailable(int,QList<Link>)));
    connect(worker, SIGNAL(titleChanged(int,int,QString,QString)), this, SIGNAL(titleChanged(int,int,QString,QString)));
    connect(worker, SIGNAL(thumbPathChanged(int,QString)), this, SIGNAL(thumbPathChanged(int,QString)));
    connect(worker, SIGNAL(nextLinkId(int)), this, SLOT(updateNextLinkId(int)));
    workerThread.start();

    QMetaObject::invokeMethod(worker, "init", Qt::BlockingQueuedConnection);
    QMetaObject::invokeMethod(worker, "getMaxTabId", Qt::BlockingQueuedConnection,
                              Q_RETURN_ARG(int, m_maxTabId));
    int maxLinkId;
    QMetaObject::invokeMethod(worker, "getMaxLinkId", Qt::BlockingQueuedConnection,
                              Q_RETURN_ARG(int, maxLinkId));
    m_nextLinkId = ++maxLinkId;
    QMetaObject::invokeMethod(worker, "getSettings", Qt::BlockingQueuedConnection,
                              Q_RETURN_ARG(SettingsMap, m_settings));
}

DBManager::~DBManager()
{
    workerThread.exit();
    // Use timeout of 500ms to guaranty we won't block
    workerThread.wait(500);
    gDbManager = 0;
}

int DBManager::getMaxTabId()
{
    return m_maxTabId;
}

int DBManager::nextLinkId()
{
    return m_nextLinkId;
}

int DBManager::createTab()
{
    QMetaObject::invokeMethod(worker, "createTab", Qt::QueuedConnection, Q_ARG(int, ++m_maxTabId));
    return m_maxTabId;
}

int DBManager::createLink(int tabId, QString url, QString title)
{
    int linkId;
    QMetaObject::invokeMethod(worker, "createLink", Qt::BlockingQueuedConnection,
                              Q_RETURN_ARG(int, linkId), Q_ARG(int, tabId),
                              Q_ARG(QString, url), Q_ARG(QString, title));

    if (linkId == m_nextLinkId) {
        ++m_nextLinkId;
    }

    return linkId;
}

void DBManager::navigateTo(int tabId, QString url, QString title, QString path)
{
    QMetaObject::invokeMethod(worker, "navigateTo", Qt::QueuedConnection,
                              Q_ARG(int, tabId), Q_ARG(QString, url),
                              Q_ARG(QString, title), Q_ARG(QString, path));
}

void DBManager::goForward(int tabId)
{
    QMetaObject::invokeMethod(worker, "goForward", Qt::BlockingQueuedConnection,
                              Q_ARG(int, tabId));
}

void DBManager::goBack(int tabId)
{
    QMetaObject::invokeMethod(worker, "goBack", Qt::BlockingQueuedConnection,
                              Q_ARG(int, tabId));
}

void DBManager::getAllTabs()
{
    QMetaObject::invokeMethod(worker, "getAllTabs", Qt::QueuedConnection);
}

void DBManager::removeTab(int tabId)
{
    QMetaObject::invokeMethod(worker, "removeTab", Qt::QueuedConnection,
                              Q_ARG(int, tabId));
}

void DBManager::updateTitle(int tabId, int linkId, QString url, QString title)
{
    QMetaObject::invokeMethod(worker, "updateTitle", Qt::QueuedConnection,
                              Q_ARG(int, tabId), Q_ARG(int, linkId), Q_ARG(QString, url), Q_ARG(QString, title));
}

void DBManager::updateThumbPath(int tabId, QString path)
{
    QMetaObject::invokeMethod(worker, "updateThumbPath", Qt::QueuedConnection,
                              Q_ARG(int, tabId), Q_ARG(QString, path));
}

void DBManager::clearHistory()
{
    m_maxTabId = 0;
    QMetaObject::invokeMethod(worker, "clearHistory", Qt::QueuedConnection);
}

void DBManager::getHistory(const QString &filter)
{
    QMetaObject::invokeMethod(worker, "getHistory", Qt::QueuedConnection, Q_ARG(QString, filter));
}

void DBManager::getTabHistory(int tabId)
{
    QMetaObject::invokeMethod(worker, "getTabHistory", Qt::QueuedConnection, Q_ARG(int, tabId));
}

void DBManager::saveSetting(QString name, QString value)
{
    m_settings.insert(name, value);
    emit settingsChanged();
    QMetaObject::invokeMethod(worker, "saveSetting", Qt::BlockingQueuedConnection,
                              Q_ARG(QString, name), Q_ARG(QString, value));
}

QString DBManager::getSetting(QString name)
{
    if (m_settings.contains(name)) {
        return m_settings.value(name);
    }

    return "";
}

void DBManager::deleteSetting(QString name)
{
    if (m_settings.contains(name)) {
        m_settings.remove(name);
        emit settingsChanged();
        QMetaObject::invokeMethod(worker, "deleteSetting", Qt::BlockingQueuedConnection,
                                  Q_ARG(QString, name));
    }
}

void DBManager::tabListAvailable(QList<Tab> tabs)
{
    if (tabs.isEmpty()) {
        m_maxTabId = 0;
    }
    emit tabsAvailable(tabs);
}

void DBManager::updateNextLinkId(int linkId)
{
    m_nextLinkId = linkId;
}
<commit_msg>Avoid warning when running unit tests<commit_after>/****************************************************************************
**
** Copyright (C) 2013 Jolla Ltd.
** Contact: Petri M. Gerdt <petri.gerdt@jollamobile.com>
**
****************************************************************************/

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "dbmanager.h"

#include <QMetaObject>

#include "dbworker.h"

static DBManager *gDbManager = 0;

DBManager *DBManager::instance()
{
    if (!gDbManager) {
        gDbManager = new DBManager();
    }
    return gDbManager;
}

DBManager::DBManager(QObject *parent)
    : QObject(parent)
    , m_maxTabId(0)
{
    qRegisterMetaType<QList<Tab> >("QList<Tab>");
    qRegisterMetaType<QList<Link> >("QList<Link>");
    qRegisterMetaType<Tab>("Tab");

    worker = new DBWorker();
    worker->moveToThread(&workerThread);

    connect(&workerThread, SIGNAL(finished()), worker, SLOT(deleteLater()));
    connect(worker, SIGNAL(tabsAvailable(QList<Tab>)), this, SLOT(tabListAvailable(QList<Tab>)));
    connect(worker, SIGNAL(historyAvailable(QList<Link>)), this, SIGNAL(historyAvailable(QList<Link>)));
    connect(worker, SIGNAL(tabHistoryAvailable(int,QList<Link>)), this, SIGNAL(tabHistoryAvailable(int,QList<Link>)));
    connect(worker, SIGNAL(titleChanged(int,int,QString,QString)), this, SIGNAL(titleChanged(int,int,QString,QString)));
    connect(worker, SIGNAL(thumbPathChanged(int,QString)), this, SIGNAL(thumbPathChanged(int,QString)));
    connect(worker, SIGNAL(nextLinkId(int)), this, SLOT(updateNextLinkId(int)));
    workerThread.start();

    QMetaObject::invokeMethod(worker, "init", Qt::BlockingQueuedConnection);
    QMetaObject::invokeMethod(worker, "getMaxTabId", Qt::BlockingQueuedConnection,
                              Q_RETURN_ARG(int, m_maxTabId));
    int maxLinkId;
    QMetaObject::invokeMethod(worker, "getMaxLinkId", Qt::BlockingQueuedConnection,
                              Q_RETURN_ARG(int, maxLinkId));
    m_nextLinkId = ++maxLinkId;
    QMetaObject::invokeMethod(worker, "getSettings", Qt::BlockingQueuedConnection,
                              Q_RETURN_ARG(SettingsMap, m_settings));
}

DBManager::~DBManager()
{
    workerThread.exit();
    // Use timeout of 500ms to guaranty we won't block
    workerThread.wait(500);
    gDbManager = 0;
    foreach (QString connectionName, QSqlDatabase::connectionNames()) {
        QSqlDatabase::removeDatabase(connectionName);
    }
}

int DBManager::getMaxTabId()
{
    return m_maxTabId;
}

int DBManager::nextLinkId()
{
    return m_nextLinkId;
}

int DBManager::createTab()
{
    QMetaObject::invokeMethod(worker, "createTab", Qt::QueuedConnection, Q_ARG(int, ++m_maxTabId));
    return m_maxTabId;
}

int DBManager::createLink(int tabId, QString url, QString title)
{
    int linkId;
    QMetaObject::invokeMethod(worker, "createLink", Qt::BlockingQueuedConnection,
                              Q_RETURN_ARG(int, linkId), Q_ARG(int, tabId),
                              Q_ARG(QString, url), Q_ARG(QString, title));

    if (linkId == m_nextLinkId) {
        ++m_nextLinkId;
    }

    return linkId;
}

void DBManager::navigateTo(int tabId, QString url, QString title, QString path)
{
    QMetaObject::invokeMethod(worker, "navigateTo", Qt::QueuedConnection,
                              Q_ARG(int, tabId), Q_ARG(QString, url),
                              Q_ARG(QString, title), Q_ARG(QString, path));
}

void DBManager::goForward(int tabId)
{
    QMetaObject::invokeMethod(worker, "goForward", Qt::BlockingQueuedConnection,
                              Q_ARG(int, tabId));
}

void DBManager::goBack(int tabId)
{
    QMetaObject::invokeMethod(worker, "goBack", Qt::BlockingQueuedConnection,
                              Q_ARG(int, tabId));
}

void DBManager::getAllTabs()
{
    QMetaObject::invokeMethod(worker, "getAllTabs", Qt::QueuedConnection);
}

void DBManager::removeTab(int tabId)
{
    QMetaObject::invokeMethod(worker, "removeTab", Qt::QueuedConnection,
                              Q_ARG(int, tabId));
}

void DBManager::updateTitle(int tabId, int linkId, QString url, QString title)
{
    QMetaObject::invokeMethod(worker, "updateTitle", Qt::QueuedConnection,
                              Q_ARG(int, tabId), Q_ARG(int, linkId), Q_ARG(QString, url), Q_ARG(QString, title));
}

void DBManager::updateThumbPath(int tabId, QString path)
{
    QMetaObject::invokeMethod(worker, "updateThumbPath", Qt::QueuedConnection,
                              Q_ARG(int, tabId), Q_ARG(QString, path));
}

void DBManager::clearHistory()
{
    m_maxTabId = 0;
    QMetaObject::invokeMethod(worker, "clearHistory", Qt::QueuedConnection);
}

void DBManager::getHistory(const QString &filter)
{
    QMetaObject::invokeMethod(worker, "getHistory", Qt::QueuedConnection, Q_ARG(QString, filter));
}

void DBManager::getTabHistory(int tabId)
{
    QMetaObject::invokeMethod(worker, "getTabHistory", Qt::QueuedConnection, Q_ARG(int, tabId));
}

void DBManager::saveSetting(QString name, QString value)
{
    m_settings.insert(name, value);
    emit settingsChanged();
    QMetaObject::invokeMethod(worker, "saveSetting", Qt::BlockingQueuedConnection,
                              Q_ARG(QString, name), Q_ARG(QString, value));
}

QString DBManager::getSetting(QString name)
{
    if (m_settings.contains(name)) {
        return m_settings.value(name);
    }

    return "";
}

void DBManager::deleteSetting(QString name)
{
    if (m_settings.contains(name)) {
        m_settings.remove(name);
        emit settingsChanged();
        QMetaObject::invokeMethod(worker, "deleteSetting", Qt::BlockingQueuedConnection,
                                  Q_ARG(QString, name));
    }
}

void DBManager::tabListAvailable(QList<Tab> tabs)
{
    if (tabs.isEmpty()) {
        m_maxTabId = 0;
    }
    emit tabsAvailable(tabs);
}

void DBManager::updateNextLinkId(int linkId)
{
    m_nextLinkId = linkId;
}
<|endoftext|>


<commit_before>/* Please refer to license.txt */

#include <sys/stat.h>
#include <errno.h>
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <dirent.h>

#include "file.hpp"

#include "../error/error.hpp"

#include "../string/string.hpp"

#include "../internal_header.hpp"

namespace mfile
{

FileManager::FileManager()
{
}

FileManager::~FileManager()
{
}

void FileManager::exportFile(std::string filepath, std::string output_data, bool overwrite) //Export a file.
{
	FILE *file = nullptr; //The file.

	if (overwrite) file = fopen(filepath.c_str(), "w+"); //Open the file for writing, overwriting whatever currently exists, if anything.
	else file = fopen(filepath.c_str(), "a"); //Open the file for writing. Do not overwrite, append.

	if (!file) //Error checking.
	{
		//cout << "Failed to open file: \"" << filepath << "\".\n"; //Let the user know there was an error.
		//cout << "Attempting to create folder...\n"; //Let the user know we're trying to create the directory.

		//TODO: This portiong needs to be put into a "make_directories_until()" function.

		//TODO: This needs to be adjusted to recursively make the missing folders.

		bool start_saving = false; //Start saving the characters from the string?
		std::string folderpath = ""; //The folderpath.
		std::string temp_string = ""; //Folderpath is initially read into this, backwards. Used for ordering it correctly.
		for (int i = filepath.length() - 1; i >= 0; --i) //Loop through and extract the folderpath
		{
			if (!start_saving && (filepath[i] == '\\' || filepath[i] == '/')) //If not already saving the characters...Check if it's a / or \ character.
			{
				start_saving = true; //Yay, end of filename found, now we can extract the folderpath.
			}
			if (start_saving) //Ok, it is saving the characters.
			{
				temp_string += filepath[i]; //Save the character.
			}
		}
		for (int i = temp_string.length() - 1; i >= 0; --i) //Now reverse the order of characters so that the folderpath is no longer backwards.
		{
			folderpath += temp_string[i]; //Save the character.
		}

		try
		{
			mkDir("./" + folderpath); //Create the folder. With error checking.
		}
		catch (...)
		{
			std::string *filename = new std::string; //The filename.
			*filename = mstring::toString(__FILE__); //Convert the char* that is filename to a string.
			std::string *message = new std::string;
			*message = "Failed to create directory: \"";
			*message += folderpath;
			*message += "\".";
			merror::Error *error = generateError(merror::FUNCTION_FAILURE, message, merror::SEVERITY_IGNORE, __LINE__, filename);
			throw error;
		}

		if (overwrite) file = fopen(filepath.c_str(), "w+"); //Open the file for writing, overwriting any currently existing file.
		else file = fopen(filepath.c_str(), "a"); //Open the file for writing. Do not overwrite, append.

		if (!file) //Error checking.
		{
			std::string *filename = new std::string; //The filename.
			*filename = mstring::toString(__FILE__); //Convert the char* that is filename to a string.
			std::string *message = new std::string;
			*message = "Failed to create file.";
			merror::Error *error = generateError(merror::FUNCTION_FAILURE, message, merror::SEVERITY_IGNORE, __LINE__, filename);
			throw error; //Failure.
		}

		//TODO: End portion that needs being put into a "make_directories_until()" function.
	}

	fprintf(file, output_data.c_str());  //Write out the string.

	fclose(file); //Close the file.
} //FileManager::exportFile()

void FileManager::mkDir(std::string path) //Create a directory at the specified location.
{
	#if OS == OS_WINDOWS //If the operating system is windows.
		if (mkdir(path.c_str()) == -1) //Create the directory.
		{
			//throw strerror(errno); //Throw an error. //TODO: Refine the error to use the error module.
			std::string *error_message = new std::string; //The error message.
			*error_message = mstring::toString(strerror(errno)); //Convert the char* that is strerror to a string.
			std::string *filename = new std::string; //The filename.
			*filename = mstring::toString(__FILE__); //Convert the char* that is filename to a string.
			merror::Error *error = generateError(merror::FUNCTION_FAILURE, error_message, merror::SEVERITY_IGNORE, __LINE__, filename);
			throw error;
		}
	#else //OS is not windows.
		if (mkdir(path.c_str(), 0777) == -1)//creating a directory
		{
			//throw strerror(errno); //Throw an error. //TODO: Refine the error to use the error module.
			std::string *error_message = new std::string; //The error message.
			*error_message = mstring::toString(strerror(errno)); //Convert the char* that is strerror to a string.
			std::string *filename = new std::string; //The filename.
			*filename = mstring::toString(__FILE__); //Convert the char* that is filename to a string.
			merror::Error *error = generateError(merror::FUNCTION_FAILURE, error_message, merror::SEVERITY_IGNORE, __LINE__, filename);
			throw error;
		}
	#endif
}

bool FileManager::directoryExists(std::string path) //Checks if specified directory exists.
{
	//This function could probably be done better with a call to an external library's superoptimised directory_exists() function.
	//But, until such a time that we have such a library, this will be used.

	//TODO: This portion probably can be put into an external function.

	//This portion of code determines the path to the directory the directory we're looking for is in.

	bool start_saving = false; //Start saving the characters from the string?
	std::string folderpath = ""; //The folderpath.
	std::string temp_string = ""; //Folderpath is initially read into this, backwards. Used for ordering it correctly.
	std::string directory_name_reverse = ""; //The name of the folder it's looking for. Reversed. This is used because the path is read backwards and everything after the slash is chopped off, thus determining the directory we're looking for's name.
	std::string directory_name = ""; //The name of the folder it's looking for.
	for (int i = path.length() - 1; i >= 0; --i) //Loop through and extract the folderpath. Pretty much the folder the folder is in.
	{
		if (!start_saving && (path[i] == '\\' || path[i] == '/') && i != path.length() - 1) //If not already saving the characters...Check if it's a / or \ character.
		{
			start_saving = true; //Nw we can extract the folderpath.
			directory_name_reverse += path[i];
		}
		else if (start_saving) //Ok, it is saving the characters.
		{
			temp_string += path[i]; //Save the character.
		}
		if (i == 0)
		{
			temp_string = "./"; //Fallback in case there's nothing for it to cleave off.
		}
	}
	for (int i = temp_string.length() - 1; i >= 0; --i) //Now reverse the order of characters so that the folderpath is no longer backwards.
	{
		folderpath += temp_string[i]; //Save the character.
	}
	for (int i = directory_name_reverse.length() - 1;  i >= 0; --i)
	{
		if (directory_name_reverse[i] != '\\' && directory_name_reverse[i] != '/') directory_name += directory_name_reverse[i];
	}
	//TODO: End portion that can be put in external function.

	//This portion of code looks at all the contents in the directory of the directory we're checking the existence of, and looks to see if the directory exists.
	//If it does, then return true. Else return false.

	std::vector<std::string> folders; //Stores all the folder names it finds.

	getFolders(folderpath, folders); //Grabs all the folders in the folder containing the folder which we're checking the existence of.

	if (folders.size() == 0)
	{
		return false; //If it found nothing...The directory definitely does not exist!
	}

	for (unsigned int i = 0; i < folders.size(); ++i)
	{
		if (folders[i] == directory_name) return true; //Yes, directory exists.
	}

	return false; //Default case: does not exist.
} //FileManager::directoryExists()

void FileManager::seperatePathFromFilename(std::string &path_with_filename, std::string &path)
{
	//Loop from the back, find the /, chop off everything.

	int count = 0;
	std::string input(path_with_filename);
	std::cout << "Starting with: " << input << "\n";
	std::string::iterator i = input.end()-1;
	bool done = false;
	while (!done)
	{
		std::cout << "i = \"" << (*i) << "\" & count = " << count << "\n";

		//If it found where the filepath ends...
		if ((*i) != '/' && (*i) != '\\')
		{
			--i; //Keep going.
			input.pop_back(); //Delete the last character.
			count++;
		}
		else
		{
			done = true;
		}
	}

	path = input;
}

void FileManager::getFolders(std::string path, std::vector<std::string> &folders) //Get all the folders in a directory.
{
	#if OS == OS_WINDOWS
		struct stat s; //Required for the Windows version of the code
	#endif

	DIR *dir ; //Open the bases folder.

	if ((dir = opendir(path.c_str())) == nullptr) //Open directory. With error checking.
	{
		std::string *filename = new std::string; //The filename.
		*filename = mstring::toString(__FILE__); //Convert the char* that is filename to a string.
		std::string *message = new std::string;
		*message = "Failed to open directory.";
		merror::Error *error = generateError(merror::FUNCTION_FAILURE, message, merror::SEVERITY_IGNORE, __LINE__, filename);
		throw error;
	}

	struct dirent *entry = readdir(dir); //The current directory entry

	while (entry != NULL) //Loop through all the folders (and files) in this directory.
	{
		#if OS == OS_WINDOWS

			//TODO: Test this to see if it works in Windows.

			stat(entry->d_name, &s);
			if (s.st_mode & S_IFDIR)
			{
				if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) //Make sure it's not the current directory, or the one containing this directory!
				{
					folders.push_back(entry->d_name);
				}
			}

			entry = readdir(dir); //Load in the next entry.

		#else

			if (entry->d_type == DT_DIR) //If the entry type is a folder.
			{
				if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) //Make sure it's not the current directory, or the one containing this directory!
				{
					folders.push_back(entry->d_name);
				}
			}

		#endif
	}

	closedir(dir);
} //FileManager::getFolders()

} //namespace mfile
<commit_msg>Oops forgot it reversed the characters.<commit_after>/* Please refer to license.txt */

#include <sys/stat.h>
#include <errno.h>
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <dirent.h>

#include "file.hpp"

#include "../error/error.hpp"

#include "../string/string.hpp"

#include "../internal_header.hpp"

namespace mfile
{

FileManager::FileManager()
{
}

FileManager::~FileManager()
{
}

void FileManager::exportFile(std::string filepath, std::string output_data, bool overwrite) //Export a file.
{
	FILE *file = nullptr; //The file.

	if (overwrite) file = fopen(filepath.c_str(), "w+"); //Open the file for writing, overwriting whatever currently exists, if anything.
	else file = fopen(filepath.c_str(), "a"); //Open the file for writing. Do not overwrite, append.

	if (!file) //Error checking.
	{
		//cout << "Failed to open file: \"" << filepath << "\".\n"; //Let the user know there was an error.
		//cout << "Attempting to create folder...\n"; //Let the user know we're trying to create the directory.

		//TODO: This portiong needs to be put into a "make_directories_until()" function.

		//TODO: This needs to be adjusted to recursively make the missing folders.

		bool start_saving = false; //Start saving the characters from the string?
		std::string folderpath = ""; //The folderpath.
		std::string temp_string = ""; //Folderpath is initially read into this, backwards. Used for ordering it correctly.
		for (int i = filepath.length() - 1; i >= 0; --i) //Loop through and extract the folderpath
		{
			if (!start_saving && (filepath[i] == '\\' || filepath[i] == '/')) //If not already saving the characters...Check if it's a / or \ character.
			{
				start_saving = true; //Yay, end of filename found, now we can extract the folderpath.
			}
			if (start_saving) //Ok, it is saving the characters.
			{
				temp_string += filepath[i]; //Save the character.
			}
		}
		for (int i = temp_string.length() - 1; i >= 0; --i) //Now reverse the order of characters so that the folderpath is no longer backwards.
		{
			folderpath += temp_string[i]; //Save the character.
		}

		try
		{
			mkDir("./" + folderpath); //Create the folder. With error checking.
		}
		catch (...)
		{
			std::string *filename = new std::string; //The filename.
			*filename = mstring::toString(__FILE__); //Convert the char* that is filename to a string.
			std::string *message = new std::string;
			*message = "Failed to create directory: \"";
			*message += folderpath;
			*message += "\".";
			merror::Error *error = generateError(merror::FUNCTION_FAILURE, message, merror::SEVERITY_IGNORE, __LINE__, filename);
			throw error;
		}

		if (overwrite) file = fopen(filepath.c_str(), "w+"); //Open the file for writing, overwriting any currently existing file.
		else file = fopen(filepath.c_str(), "a"); //Open the file for writing. Do not overwrite, append.

		if (!file) //Error checking.
		{
			std::string *filename = new std::string; //The filename.
			*filename = mstring::toString(__FILE__); //Convert the char* that is filename to a string.
			std::string *message = new std::string;
			*message = "Failed to create file.";
			merror::Error *error = generateError(merror::FUNCTION_FAILURE, message, merror::SEVERITY_IGNORE, __LINE__, filename);
			throw error; //Failure.
		}

		//TODO: End portion that needs being put into a "make_directories_until()" function.
	}

	fprintf(file, output_data.c_str());  //Write out the string.

	fclose(file); //Close the file.
} //FileManager::exportFile()

void FileManager::mkDir(std::string path) //Create a directory at the specified location.
{
	#if OS == OS_WINDOWS //If the operating system is windows.
		if (mkdir(path.c_str()) == -1) //Create the directory.
		{
			//throw strerror(errno); //Throw an error. //TODO: Refine the error to use the error module.
			std::string *error_message = new std::string; //The error message.
			*error_message = mstring::toString(strerror(errno)); //Convert the char* that is strerror to a string.
			std::string *filename = new std::string; //The filename.
			*filename = mstring::toString(__FILE__); //Convert the char* that is filename to a string.
			merror::Error *error = generateError(merror::FUNCTION_FAILURE, error_message, merror::SEVERITY_IGNORE, __LINE__, filename);
			throw error;
		}
	#else //OS is not windows.
		if (mkdir(path.c_str(), 0777) == -1)//creating a directory
		{
			//throw strerror(errno); //Throw an error. //TODO: Refine the error to use the error module.
			std::string *error_message = new std::string; //The error message.
			*error_message = mstring::toString(strerror(errno)); //Convert the char* that is strerror to a string.
			std::string *filename = new std::string; //The filename.
			*filename = mstring::toString(__FILE__); //Convert the char* that is filename to a string.
			merror::Error *error = generateError(merror::FUNCTION_FAILURE, error_message, merror::SEVERITY_IGNORE, __LINE__, filename);
			throw error;
		}
	#endif
}

bool FileManager::directoryExists(std::string path) //Checks if specified directory exists.
{
	//This function could probably be done better with a call to an external library's superoptimised directory_exists() function.
	//But, until such a time that we have such a library, this will be used.

	//TODO: This portion probably can be put into an external function.

	//This portion of code determines the path to the directory the directory we're looking for is in.

	bool start_saving = false; //Start saving the characters from the string?
	std::string folderpath = ""; //The folderpath.
	std::string temp_string = ""; //Folderpath is initially read into this, backwards. Used for ordering it correctly.
	std::string directory_name_reverse = ""; //The name of the folder it's looking for. Reversed. This is used because the path is read backwards and everything after the slash is chopped off, thus determining the directory we're looking for's name.
	std::string directory_name = ""; //The name of the folder it's looking for.
	for (int i = path.length() - 1; i >= 0; --i) //Loop through and extract the folderpath. Pretty much the folder the folder is in.
	{
		if (!start_saving && (path[i] == '\\' || path[i] == '/') && i != path.length() - 1) //If not already saving the characters...Check if it's a / or \ character.
		{
			start_saving = true; //Nw we can extract the folderpath.
			directory_name_reverse += path[i];
		}
		else if (start_saving) //Ok, it is saving the characters.
		{
			temp_string += path[i]; //Save the character.
		}
		if (i == 0)
		{
			temp_string = "/."; //Fallback in case there's nothing for it to cleave off.
		}
	}
	for (int i = temp_string.length() - 1; i >= 0; --i) //Now reverse the order of characters so that the folderpath is no longer backwards.
	{
		folderpath += temp_string[i]; //Save the character.
	}
	for (int i = directory_name_reverse.length() - 1;  i >= 0; --i)
	{
		if (directory_name_reverse[i] != '\\' && directory_name_reverse[i] != '/') directory_name += directory_name_reverse[i];
	}
	//TODO: End portion that can be put in external function.

	//This portion of code looks at all the contents in the directory of the directory we're checking the existence of, and looks to see if the directory exists.
	//If it does, then return true. Else return false.

	std::vector<std::string> folders; //Stores all the folder names it finds.

	getFolders(folderpath, folders); //Grabs all the folders in the folder containing the folder which we're checking the existence of.

	if (folders.size() == 0)
	{
		return false; //If it found nothing...The directory definitely does not exist!
	}

	for (unsigned int i = 0; i < folders.size(); ++i)
	{
		if (folders[i] == directory_name) return true; //Yes, directory exists.
	}

	return false; //Default case: does not exist.
} //FileManager::directoryExists()

void FileManager::seperatePathFromFilename(std::string &path_with_filename, std::string &path)
{
	//Loop from the back, find the /, chop off everything.

	int count = 0;
	std::string input(path_with_filename);
	std::cout << "Starting with: " << input << "\n";
	std::string::iterator i = input.end()-1;
	bool done = false;
	while (!done)
	{
		std::cout << "i = \"" << (*i) << "\" & count = " << count << "\n";

		//If it found where the filepath ends...
		if ((*i) != '/' && (*i) != '\\')
		{
			--i; //Keep going.
			input.pop_back(); //Delete the last character.
			count++;
		}
		else
		{
			done = true;
		}
	}

	path = input;
}

void FileManager::getFolders(std::string path, std::vector<std::string> &folders) //Get all the folders in a directory.
{
	#if OS == OS_WINDOWS
		struct stat s; //Required for the Windows version of the code
	#endif

	DIR *dir ; //Open the bases folder.

	if ((dir = opendir(path.c_str())) == nullptr) //Open directory. With error checking.
	{
		std::string *filename = new std::string; //The filename.
		*filename = mstring::toString(__FILE__); //Convert the char* that is filename to a string.
		std::string *message = new std::string;
		*message = "Failed to open directory.";
		merror::Error *error = generateError(merror::FUNCTION_FAILURE, message, merror::SEVERITY_IGNORE, __LINE__, filename);
		throw error;
	}

	struct dirent *entry = readdir(dir); //The current directory entry

	while (entry != NULL) //Loop through all the folders (and files) in this directory.
	{
		#if OS == OS_WINDOWS

			//TODO: Test this to see if it works in Windows.

			stat(entry->d_name, &s);
			if (s.st_mode & S_IFDIR)
			{
				if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) //Make sure it's not the current directory, or the one containing this directory!
				{
					folders.push_back(entry->d_name);
				}
			}

			entry = readdir(dir); //Load in the next entry.

		#else

			if (entry->d_type == DT_DIR) //If the entry type is a folder.
			{
				if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) //Make sure it's not the current directory, or the one containing this directory!
				{
					folders.push_back(entry->d_name);
				}
			}

		#endif
	}

	closedir(dir);
} //FileManager::getFolders()

} //namespace mfile
<|endoftext|>