<commit_before>#include "version.hpp"

#include <cutehmi/CuteHMI.hpp>
#include <cutehmi/ProjectModel.hpp>
#include <cutehmi/ErrorInfo.hpp>

#include <cutehmi/xml/ProjectBackend.hpp>

#include <cutehmi/app/CuteApp.hpp>

//<workaround id="cutehmi_view-4" target="Qt" cause="bug">
#include <QApplication>
// Instead of:
//  #include <QGuiApplication>
//</workaround>

#include <QQmlApplicationEngine>
#include <QIcon>
#include <QDir>
#include <QtDebug>
#include <QCommandLineParser>
#include <QQmlContext>
#include <QUrl>
#include <QCursor>
#include <QTranslator>
#include <QLibraryInfo>
#include <QFile>

namespace cutehmi {
namespace view {

void loadXMLFile(const QString & filePath, Project & project, QQmlContext & qmlContext)
{
	if (filePath.isEmpty()) {
		Prompt::Warning(QObject::tr("Empty filename has been provided."));
		return;
	}

	qDebug() << "Loading project file '" << filePath << "'...";

	QFile file(filePath);
	xml::ProjectBackend xmlBackend(& file, & qmlContext);
	try {
		project.load(xmlBackend);
		Notification::Note(QObject::tr("Succesfuly loaded project file '%1'.").arg(filePath));
	} catch (const xml::ProjectBackend::DeviceOpenReadException & ) {
		if (!QFileInfo(filePath).exists())
			Prompt::Warning(QObject::tr("Could not load project file. File '%1' does not exist.").arg(filePath));
		else
			Prompt::Warning(QObject::tr("Could not load project file. File '%1' could not be opened for reading.").arg(filePath));
	} catch (const Exception & e) {
		Prompt::Critical(QObject::tr("Error while parsing '%1' document.").arg(filePath) + "\n\n" + e.what());
	}
}

}
}

int main(int argc, char * argv[])
{
	QCoreApplication::setOrganizationDomain("cutehmi");
	QCoreApplication::setApplicationName("CuteHMI");
	QCoreApplication::setApplicationVersion(CUTEHMI_APP_VERSION);

	if (qgetenv("QT_IM_MODULE").isEmpty())
		qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard"));
	qDebug() << "Input method: " << qgetenv("QT_IM_MODULE");

	if (qgetenv("QT_IM_MODULE") == "qtvirtualkeyboard") {
		if (qgetenv("QT_VIRTUALKEYBOARD_LAYOUT_PATH").isEmpty())
			qputenv("QT_VIRTUALKEYBOARD_LAYOUT_PATH", QByteArray(QDir("../layouts").absolutePath().toLocal8Bit()));
		qDebug() << "Qt Virtual Keyboard layouts path: " << qgetenv("QT_VIRTUALKEYBOARD_LAYOUT_PATH");
	}

//<principle id="Qt-Qt_5_7_0_Reference_Documentation-Threads_and_QObjects-QObject_Reentrancy-creating_QObjects_before_QApplication">
// "In general, creating QObjects before the QApplication is not supported and can lead to weird crashes on exit, depending on the
//	platform. This means static instances of QObject are also not supported. A properly structured single or multi-threaded application
//	should make the QApplication be the first created, and last destroyed QObject."

	//<workaround id="cutehmi_view-4" target="Qt" cause="bug">
	QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
	cutehmi::app::CuteApp app(argc, argv);
	// Instead of:
	//	QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
	//	QGuiApplication app(argc, argv);
	//<workaround>
	app.setWindowIcon(QIcon(":/img/icon.png"));

	QCommandLineParser cmd;
	cmd.setApplicationDescription("CuteHMI");
	cmd.addHelpOption();
	cmd.addVersionOption();
	QCommandLineOption fullScreenOption({"f", "fullscreen"}, QCoreApplication::translate("main", "Run application in full screen mode."));
	cmd.addOption(fullScreenOption);
	QCommandLineOption projectOption({"p", "project"}, QCoreApplication::translate("main", "Load CuteHMI project <file>."), QCoreApplication::translate("main", "file"));
	cmd.addOption(projectOption);
	QCommandLineOption hideCursorOption({"t", "touch"}, QCoreApplication::translate("main", "Touch screen (hides mouse cursor)."));
	cmd.addOption(hideCursorOption);
	QCommandLineOption styleOption("qstyle", QCoreApplication::translate("main", "Set Qt Quick <style>."), QCoreApplication::translate("main", "style"));
	cmd.addOption(styleOption);
	QCommandLineOption langOption("lang", QCoreApplication::translate("main", "Choose application <language>."), QCoreApplication::translate("main", "language"));
	cmd.addOption(langOption);
	QCommandLineOption basedirOption("basedir", QCoreApplication::translate("main", "Set base directory to <dir>."), QCoreApplication::translate("main", "dir"));
	cmd.addOption(basedirOption);
	cmd.process(app);

	qDebug() << "Default locale: " << QLocale();

	QTranslator qtTranslator;
	if (cmd.isSet(langOption))
		qtTranslator.load("qt_" + cmd.value(langOption), QLibraryInfo::location(QLibraryInfo::TranslationsPath));
	else
		qtTranslator.load("qt_" + QLocale::system().name(), QLibraryInfo::location(QLibraryInfo::TranslationsPath));
	app.installTranslator(& qtTranslator);

	if (cmd.isSet(styleOption)) {
		qputenv("QT_QUICK_CONTROLS_STYLE", cmd.value(styleOption).toLocal8Bit());
		qDebug() << "Qt Quick style: " << cmd.value(styleOption);
	}

	if (cmd.isSet(hideCursorOption))
		QGuiApplication::setOverrideCursor(QCursor(Qt::BlankCursor));
	//<workaround id="cutehmi_view-5" target="Qt" cause="bug">
	// When run on raw Xorg server application does not show up cursor unless some controls are hovered.
	else
		QGuiApplication::setOverrideCursor(QCursor(Qt::ArrowCursor));
	//</workaround>

	QDir baseDir(QCoreApplication::applicationDirPath());
	if (cmd.isSet(basedirOption))
		baseDir = cmd.value(basedirOption);
	QString baseDirPath = baseDir.absolutePath() + "/";
	qDebug() << "Base directory: " << baseDirPath;

	qDebug() << "Library paths: " << QCoreApplication::libraryPaths();

	std::unique_ptr<QQmlApplicationEngine> engine(new QQmlApplicationEngine);
	engine->addImportPath(baseDirPath + "../QML");
	qDebug() << "QML import paths: " << engine->importPathList();
	engine->rootContext()->setContextProperty("cutehmi_bin_mainScreenURL", "qrc:/qml/DefaultScreen.qml");
	engine->load(QUrl(QStringLiteral("qrc:/qml/MainWindow.qml")));

	if (!cmd.value(projectOption).isNull()) {
		cutehmi::CuteHMI & cuteHMI = cutehmi::CuteHMI::Instance();
		cutehmi::view::loadXMLFile(baseDirPath + cmd.value(projectOption), *cuteHMI.project(), *engine->rootContext());

		cutehmi::ProjectNode * appNode = cuteHMI.project()->model()->root().child("cutehmi_app_1");
		if (appNode) {
			QString source;
			appNode->invoke("cutehmi::app::MainScreen", "source", Q_RETURN_ARG(QString, source));
			QUrl sourceUrl(source);
			if (sourceUrl.isValid()) {
				// Assure that URL is not mixing relative path with explicitly specified scheme, which is forbidden. QUrl::isValid() doesn't check this out.
				if (!sourceUrl.scheme().isEmpty() && QDir::isRelativePath(sourceUrl.path()))
					cutehmi::Prompt::Critical(QObject::tr("URL '%1' contains relative path along with URL scheme, which is forbidden.").arg(sourceUrl.url()));
				else {
					// If source URL is relative (does not contain scheme), then make absolute URL: file:///baseDirPath/sourceUrl.
					if (sourceUrl.isRelative())
						sourceUrl = QUrl::fromLocalFile(baseDirPath).resolved(sourceUrl);
					// Check if file exists and eventually set context property.
					if (sourceUrl.isLocalFile() && !QFile::exists(sourceUrl.toLocalFile()))
						cutehmi::Prompt::Critical(QObject::tr("Main screen file '%1' does not exist.").arg(sourceUrl.url()));
					else
						engine->rootContext()->setContextProperty("cutehmi_bin_mainScreenURL", sourceUrl.url());
				}
			} else
				cutehmi::Prompt::Critical(QObject::tr("Invalid format of main screen URL '%1'.").arg(source));
		}
	}

	//<principle id="Qt-Qt_5_9_1_Reference_Documentation-Qt_Core-C++_Classes-QCoreApplication-exec">
	// "We recommend that you connect clean-up code to the aboutToQuit() signal, instead of putting it in your application's main() function because on some
	//  platforms the exec() call may not return. For example, on Windows when the user logs off, the system terminates the process after Qt closes all top-level
	//  windows. Hence, there is no guarantee that the application will have time to exit its event loop and execute code at the end of the main() function after
	//  the exec() call."
	QObject::connect(& app, & cutehmi::app::CuteApp::aboutToQuit, [&]() {
		// It's quite important to destroy "engine" before cutehmi::CuteHMI::Instance() members, because they
		// may still be used by some QML components (for example in "Component.onDestroyed" handlers).
		engine.reset();

		cutehmi::CuteHMI::Destroy();

		if (cmd.isSet(hideCursorOption))
			QGuiApplication::restoreOverrideCursor();
		//<workaround ref="cutehmi_view-5">
		else
			QGuiApplication::restoreOverrideCursor();
		//</workaround>
	});
	//</principle>

	return app.exec();

	//</principle>
}

//(c)MP: Copyright © 2017, Michal Policht. All rights reserved.
//(c)MP: 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/.
<commit_msg>Change 'basedir' option semantics.<commit_after>#include "version.hpp"

#include <cutehmi/CuteHMI.hpp>
#include <cutehmi/ProjectModel.hpp>
#include <cutehmi/ErrorInfo.hpp>

#include <cutehmi/xml/ProjectBackend.hpp>

#include <cutehmi/app/CuteApp.hpp>

//<workaround id="cutehmi_view-4" target="Qt" cause="bug">
#include <QApplication>
// Instead of:
//  #include <QGuiApplication>
//</workaround>

#include <QQmlApplicationEngine>
#include <QIcon>
#include <QDir>
#include <QtDebug>
#include <QCommandLineParser>
#include <QQmlContext>
#include <QUrl>
#include <QCursor>
#include <QTranslator>
#include <QLibraryInfo>
#include <QFile>

namespace cutehmi {
namespace view {

void loadXMLFile(const QString & filePath, Project & project, QQmlContext & qmlContext)
{
	if (filePath.isEmpty()) {
		Prompt::Warning(QObject::tr("Empty filename has been provided."));
		return;
	}

	qDebug() << "Loading project file '" << filePath << "'...";

	QFile file(filePath);
	xml::ProjectBackend xmlBackend(& file, & qmlContext);
	try {
		project.load(xmlBackend);
		Notification::Note(QObject::tr("Succesfuly loaded project file '%1'.").arg(filePath));
	} catch (const xml::ProjectBackend::DeviceOpenReadException & ) {
		if (!QFileInfo(filePath).exists())
			Prompt::Warning(QObject::tr("Could not load project file. File '%1' does not exist.").arg(filePath));
		else
			Prompt::Warning(QObject::tr("Could not load project file. File '%1' could not be opened for reading.").arg(filePath));
	} catch (const Exception & e) {
		Prompt::Critical(QObject::tr("Error while parsing '%1' document.").arg(filePath) + "\n\n" + e.what());
	}
}

}
}

int main(int argc, char * argv[])
{
	QCoreApplication::setOrganizationDomain("cutehmi");
	QCoreApplication::setApplicationName("CuteHMI");
	QCoreApplication::setApplicationVersion(CUTEHMI_APP_VERSION);

	if (qgetenv("QT_IM_MODULE").isEmpty())
		qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard"));
	qDebug() << "Input method: " << qgetenv("QT_IM_MODULE");

	if (qgetenv("QT_IM_MODULE") == "qtvirtualkeyboard") {
		if (qgetenv("QT_VIRTUALKEYBOARD_LAYOUT_PATH").isEmpty())
			qputenv("QT_VIRTUALKEYBOARD_LAYOUT_PATH", QByteArray(QDir("../layouts").absolutePath().toLocal8Bit()));
		qDebug() << "Qt Virtual Keyboard layouts path: " << qgetenv("QT_VIRTUALKEYBOARD_LAYOUT_PATH");
	}

//<principle id="Qt-Qt_5_7_0_Reference_Documentation-Threads_and_QObjects-QObject_Reentrancy-creating_QObjects_before_QApplication">
// "In general, creating QObjects before the QApplication is not supported and can lead to weird crashes on exit, depending on the
//	platform. This means static instances of QObject are also not supported. A properly structured single or multi-threaded application
//	should make the QApplication be the first created, and last destroyed QObject."

	//<workaround id="cutehmi_view-4" target="Qt" cause="bug">
	QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
	cutehmi::app::CuteApp app(argc, argv);
	// Instead of:
	//	QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
	//	QGuiApplication app(argc, argv);
	//<workaround>
	app.setWindowIcon(QIcon(":/img/icon.png"));

	QCommandLineParser cmd;
	cmd.setApplicationDescription("CuteHMI");
	cmd.addHelpOption();
	cmd.addVersionOption();
	QCommandLineOption fullScreenOption({"f", "fullscreen"}, QCoreApplication::translate("main", "Run application in full screen mode."));
	cmd.addOption(fullScreenOption);
	QCommandLineOption projectOption({"p", "project"}, QCoreApplication::translate("main", "Load CuteHMI project <file>."), QCoreApplication::translate("main", "file"));
	cmd.addOption(projectOption);
	QCommandLineOption hideCursorOption({"t", "touch"}, QCoreApplication::translate("main", "Touch screen (hides mouse cursor)."));
	cmd.addOption(hideCursorOption);
	QCommandLineOption styleOption("qstyle", QCoreApplication::translate("main", "Set Qt Quick <style>."), QCoreApplication::translate("main", "style"));
	cmd.addOption(styleOption);
	QCommandLineOption langOption("lang", QCoreApplication::translate("main", "Choose application <language>."), QCoreApplication::translate("main", "language"));
	cmd.addOption(langOption);
	QCommandLineOption basedirOption("basedir", QCoreApplication::translate("main", "Set base directory to <dir>."), QCoreApplication::translate("main", "dir"));
	cmd.addOption(basedirOption);
	cmd.process(app);

	qDebug() << "Default locale: " << QLocale();

	QTranslator qtTranslator;
	if (cmd.isSet(langOption))
		qtTranslator.load("qt_" + cmd.value(langOption), QLibraryInfo::location(QLibraryInfo::TranslationsPath));
	else
		qtTranslator.load("qt_" + QLocale::system().name(), QLibraryInfo::location(QLibraryInfo::TranslationsPath));
	app.installTranslator(& qtTranslator);

	if (cmd.isSet(styleOption)) {
		qputenv("QT_QUICK_CONTROLS_STYLE", cmd.value(styleOption).toLocal8Bit());
		qDebug() << "Qt Quick style: " << cmd.value(styleOption);
	}

	if (cmd.isSet(hideCursorOption))
		QGuiApplication::setOverrideCursor(QCursor(Qt::BlankCursor));
	//<workaround id="cutehmi_view-5" target="Qt" cause="bug">
	// When run on raw Xorg server application does not show up cursor unless some controls are hovered.
	else
		QGuiApplication::setOverrideCursor(QCursor(Qt::ArrowCursor));
	//</workaround>

	QDir baseDir(QCoreApplication::applicationDirPath() + "/..");
	if (cmd.isSet(basedirOption))
		baseDir = cmd.value(basedirOption);
	QString baseDirPath = baseDir.absolutePath() + "/";
	qDebug() << "Base directory: " << baseDirPath;

	qDebug() << "Library paths: " << QCoreApplication::libraryPaths();

	std::unique_ptr<QQmlApplicationEngine> engine(new QQmlApplicationEngine);
	engine->addImportPath(baseDirPath + "QML");
	qDebug() << "QML import paths: " << engine->importPathList();
	engine->rootContext()->setContextProperty("cutehmi_bin_mainScreenURL", "qrc:/qml/DefaultScreen.qml");
	engine->load(QUrl(QStringLiteral("qrc:/qml/MainWindow.qml")));

	if (!cmd.value(projectOption).isNull()) {
		cutehmi::CuteHMI & cuteHMI = cutehmi::CuteHMI::Instance();
		cutehmi::view::loadXMLFile(baseDirPath + cmd.value(projectOption), *cuteHMI.project(), *engine->rootContext());

		cutehmi::ProjectNode * appNode = cuteHMI.project()->model()->root().child("cutehmi_app_1");
		if (appNode) {
			QString source;
			appNode->invoke("cutehmi::app::MainScreen", "source", Q_RETURN_ARG(QString, source));
			QUrl sourceUrl(source);
			if (sourceUrl.isValid()) {
				// Assure that URL is not mixing relative path with explicitly specified scheme, which is forbidden. QUrl::isValid() doesn't check this out.
				if (!sourceUrl.scheme().isEmpty() && QDir::isRelativePath(sourceUrl.path()))
					cutehmi::Prompt::Critical(QObject::tr("URL '%1' contains relative path along with URL scheme, which is forbidden.").arg(sourceUrl.url()));
				else {
					// If source URL is relative (does not contain scheme), then make absolute URL: file:///baseDirPath/sourceUrl.
					if (sourceUrl.isRelative())
						sourceUrl = QUrl::fromLocalFile(baseDirPath).resolved(sourceUrl);
					// Check if file exists and eventually set context property.
					if (sourceUrl.isLocalFile() && !QFile::exists(sourceUrl.toLocalFile()))
						cutehmi::Prompt::Critical(QObject::tr("Main screen file '%1' does not exist.").arg(sourceUrl.url()));
					else
						engine->rootContext()->setContextProperty("cutehmi_bin_mainScreenURL", sourceUrl.url());
				}
			} else
				cutehmi::Prompt::Critical(QObject::tr("Invalid format of main screen URL '%1'.").arg(source));
		}
	}

	//<principle id="Qt-Qt_5_9_1_Reference_Documentation-Qt_Core-C++_Classes-QCoreApplication-exec">
	// "We recommend that you connect clean-up code to the aboutToQuit() signal, instead of putting it in your application's main() function because on some
	//  platforms the exec() call may not return. For example, on Windows when the user logs off, the system terminates the process after Qt closes all top-level
	//  windows. Hence, there is no guarantee that the application will have time to exit its event loop and execute code at the end of the main() function after
	//  the exec() call."
	QObject::connect(& app, & cutehmi::app::CuteApp::aboutToQuit, [&]() {
		// It's quite important to destroy "engine" before cutehmi::CuteHMI::Instance() members, because they
		// may still be used by some QML components (for example in "Component.onDestroyed" handlers).
		engine.reset();

		cutehmi::CuteHMI::Destroy();

		if (cmd.isSet(hideCursorOption))
			QGuiApplication::restoreOverrideCursor();
		//<workaround ref="cutehmi_view-5">
		else
			QGuiApplication::restoreOverrideCursor();
		//</workaround>
	});
	//</principle>

	return app.exec();

	//</principle>
}

//(c)MP: Copyright © 2017, Michal Policht. All rights reserved.
//(c)MP: 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/.
<|endoftext|>


<commit_before>/*************************************************************************
This software allows for filtering in high-dimensional observation and
state spaces, as described in

M. Wuthrich, P. Pastor, M. Kalakrishnan, J. Bohg, and S. Schaal.
Probabilistic Object Tracking using a Range Camera
IEEE/RSJ Intl Conf on Intelligent Robots and Systems, 2013

In a publication based on this software pleace cite the above reference.

Copyright (C) 2014  Manuel Wuthrich

This program 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.

This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
*************************************************************************/

#ifndef FAST_FILTERING_FILTERS_STOCHASTIC_RAO_BLACKWELL_COORDINATE_PARTICLE_FILTER_HPP
#define FAST_FILTERING_FILTERS_STOCHASTIC_RAO_BLACKWELL_COORDINATE_PARTICLE_FILTER_HPP

#include <vector>
#include <limits>
#include <string>

#include <boost/shared_ptr.hpp>

#include <Eigen/Core>

#include <ff/utils/assertions.hpp>
#include <ff/utils/profiling.hpp>
#include <fl/util/traits.hpp>
#include <ff/utils/helper_functions.hpp>
#include <fl/distribution/gaussian.hpp>
#include <ff/distributions/sum_of_deltas.hpp>
#include <fl/distribution/interface/gaussian_map.hpp>
#include <ff/models/observation_models/interfaces/rao_blackwell_observation_model.hpp>
#include <ff/models/process_models/interfaces/stationary_process_model.hpp>

namespace fl
{

template<typename ProcessModel, typename ObservationModel>
class RaoBlackwellCoordinateParticleFilter
{
public:
    typedef typename Traits<ProcessModel>::Scalar Scalar;
    typedef typename Traits<ProcessModel>::State  State;
    typedef typename Traits<ProcessModel>::Input  Input;
    typedef typename Traits<ProcessModel>::Noise  Noise;

    typedef typename ObservationModel::Observation Observation;

    // state distribution
    typedef SumOfDeltas<State> StateDistributionType;

public:
    RaoBlackwellCoordinateParticleFilter(
            const boost::shared_ptr<ProcessModel> process_model,
            const boost::shared_ptr<ObservationModel>  observation_model,
            const std::vector<std::vector<size_t>>& sampling_blocks,
            const Scalar& max_kl_divergence = 0):
        observation_model_(observation_model),
        process_model_(process_model),
        max_kl_divergence_(max_kl_divergence)
    {
        static_assert_base(
            ProcessModel,
            StationaryProcessModel<State, Input>);

        static_assert_base(
            ProcessModel,
            GaussianMap<State, Noise>);

        static_assert_base(
            ObservationModel,
            RaoBlackwellObservationModel<State, Observation>);

        SamplingBlocks(sampling_blocks);
    }

    virtual ~RaoBlackwellCoordinateParticleFilter() {}

public:
    void Filter(const Observation&  observation,
                const Scalar&       delta_time,
                const Input&        input)
    {
        observation_model_->SetObservation(observation, delta_time);

        loglikes_ = std::vector<Scalar>(samples_.size(), 0);
        noises_ = std::vector<Noise>(samples_.size(), Noise::Zero(process_model_->NoiseDimension()));
        next_samples_ = samples_;

        for(size_t block_index = 0; block_index < sampling_blocks_.size(); block_index++)
        {
            INIT_PROFILING;
            for(size_t particle_index = 0; particle_index < samples_.size(); particle_index++)
            {
                for(size_t i = 0; i < sampling_blocks_[block_index].size(); i++)
                    noises_[particle_index](sampling_blocks_[block_index][i]) = unit_gaussian_.Sample()(0);
            }
            MEASURE("sampling");
            for(size_t particle_index = 0; particle_index < samples_.size(); particle_index++)
            {
                process_model_->Condition(delta_time,
                                          samples_[particle_index],
                                          input);
            }
            MEASURE("conditioning");
            for(size_t particle_index = 0; particle_index < samples_.size(); particle_index++)
            {
                next_samples_[particle_index] = process_model_->MapStandardGaussian(noises_[particle_index]);
            }
            MEASURE("propagation");

            bool update_occlusions = (block_index == sampling_blocks_.size()-1);
            std::vector<Scalar> new_loglikes = observation_model_->Loglikes(next_samples_,
                                                                           indices_,
                                                                           update_occlusions);
            MEASURE("evaluation");
            std::vector<Scalar> delta_loglikes(new_loglikes.size());
            for(size_t i = 0; i < delta_loglikes.size(); i++)
                delta_loglikes[i] = new_loglikes[i] - loglikes_[i];
            loglikes_ = new_loglikes;
            UpdateWeights(delta_loglikes);
            MEASURE("updating weights");

        }

        samples_ = next_samples_;
        state_distribution_.SetDeltas(samples_); // not sure whether this is the right place

    }

    void Resample(const size_t& sample_count)
    {
        std::vector<State> samples(sample_count);
        std::vector<size_t> indices(sample_count);
        std::vector<Noise> noises(sample_count);
        std::vector<State> next_samples(sample_count);
        std::vector<Scalar> loglikes(sample_count);

        fl::hf::DiscreteSampler sampler(log_weights_);

        for(size_t i = 0; i < sample_count; i++)
        {
            size_t index = sampler.Sample();

            samples[i]      = samples_[index];
            indices[i]      = indices_[index];
            noises[i]       = noises_[index];
            next_samples[i] = next_samples_[index];
            loglikes[i]     = loglikes_[index];
        }
        samples_        = samples;
        indices_        = indices;
        noises_         = noises;
        next_samples_   = next_samples;
        loglikes_       = loglikes;

        log_weights_        = std::vector<Scalar>(samples_.size(), 0.);

        state_distribution_.SetDeltas(samples_); // not sure whether this is the right place
    }

private:
    void UpdateWeights(std::vector<Scalar> log_weight_diffs)
    {
        for(size_t i = 0; i < log_weight_diffs.size(); i++)
            log_weights_[i] += log_weight_diffs[i];

        std::vector<Scalar> weights = log_weights_;
        fl::hf::Sort(weights, 1);

        for(int i = weights.size() - 1; i >= 0; i--)
            weights[i] -= weights[0];

        weights = fl::hf::Apply<Scalar, Scalar>(weights, std::exp);
        weights = fl::hf::SetSum(weights, Scalar(1));

        // compute KL divergence to uniform distribution KL(p|u)
        Scalar kl_divergence = std::log(Scalar(weights.size()));
        for(size_t i = 0; i < weights.size(); i++)
        {
            Scalar information = - std::log(weights[i]) * weights[i];
            if(!std::isfinite(information))
                information = 0; // the limit for weight -> 0 is equal to 0
            kl_divergence -= information;
        }

        if(kl_divergence > max_kl_divergence_)
            Resample(samples_.size());
    }

public:
    // set
    void Samples(const std::vector<State >& samples)
    {
        samples_ = samples;
        indices_ = std::vector<size_t>(samples_.size(), 0); observation_model_->Reset();
        log_weights_ = std::vector<Scalar>(samples_.size(), 0);
    }
    void SamplingBlocks(const std::vector<std::vector<size_t>>& sampling_blocks)
    {
        sampling_blocks_ = sampling_blocks;

        // make sure sizes are consistent
        size_t dimension = 0;
        for(size_t i = 0; i < sampling_blocks_.size(); i++)
            for(size_t j = 0; j < sampling_blocks_[i].size(); j++)
                dimension++;

        if(dimension != process_model_->NoiseDimension())
        {
            std::cout << "the dimension of the sampling blocks is " << dimension
                      << " while the dimension of the noise is "
                      << process_model_->NoiseDimension() << std::endl;
            exit(-1);
        }
    }

    // get
    const std::vector<State>& Samples() const
    {
        return samples_;
    }

    StateDistributionType& StateDistribution()
    {
        return state_distribution_;
    }

private:
    // internal state TODO: THIS COULD BE MADE MORE COMPACT!!
    StateDistributionType state_distribution_;

    std::vector<State > samples_;
    std::vector<size_t> indices_;
    std::vector<Scalar>  log_weights_;
    std::vector<Noise> noises_;
    std::vector<State> next_samples_;
    std::vector<Scalar> loglikes_;

    // observation model
    boost::shared_ptr<ObservationModel> observation_model_;

    // process model
    boost::shared_ptr<ProcessModel> process_model_;

    // parameters
    std::vector<std::vector<size_t>> sampling_blocks_;
    Scalar max_kl_divergence_;

    // distribution for sampling
    Gaussian<Eigen::Matrix<Scalar,1,1>> unit_gaussian_;
};

}

#endif
<commit_msg>Filter function fixed<commit_after>/*************************************************************************
This software allows for filtering in high-dimensional observation and
state spaces, as described in

M. Wuthrich, P. Pastor, M. Kalakrishnan, J. Bohg, and S. Schaal.
Probabilistic Object Tracking using a Range Camera
IEEE/RSJ Intl Conf on Intelligent Robots and Systems, 2013

In a publication based on this software pleace cite the above reference.

Copyright (C) 2014  Manuel Wuthrich

This program 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.

This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
*************************************************************************/

#ifndef FAST_FILTERING_FILTERS_STOCHASTIC_RAO_BLACKWELL_COORDINATE_PARTICLE_FILTER_HPP
#define FAST_FILTERING_FILTERS_STOCHASTIC_RAO_BLACKWELL_COORDINATE_PARTICLE_FILTER_HPP

#include <vector>
#include <limits>
#include <string>

#include <boost/shared_ptr.hpp>

#include <Eigen/Core>

#include <fl/util/assertions.hpp>
#include <fl/util/profiling.hpp>
#include <fl/util/traits.hpp>
#include <ff/utils/helper_functions.hpp>
#include <fl/distribution/gaussian.hpp>
#include <ff/distributions/sum_of_deltas.hpp>
#include <fl/distribution/interface/gaussian_map.hpp>
#include <ff/models/observation_models/interfaces/rao_blackwell_observation_model.hpp>
#include <ff/models/process_models/interfaces/stationary_process_model.hpp>

namespace fl
{

template<typename ProcessModel, typename ObservationModel>
class RaoBlackwellCoordinateParticleFilter
{
public:
    typedef typename Traits<ProcessModel>::Scalar Scalar;
    typedef typename Traits<ProcessModel>::State  State;
    typedef typename Traits<ProcessModel>::Input  Input;
    typedef typename Traits<ProcessModel>::Noise  Noise;

    typedef typename ObservationModel::Observation Observation;

    // state distribution
    typedef SumOfDeltas<State> StateDistributionType;

public:
    RaoBlackwellCoordinateParticleFilter(
            const boost::shared_ptr<ProcessModel> process_model,
            const boost::shared_ptr<ObservationModel>  observation_model,
            const std::vector<std::vector<size_t>>& sampling_blocks,
            const Scalar& max_kl_divergence = 0):
        observation_model_(observation_model),
        process_model_(process_model),
        max_kl_divergence_(max_kl_divergence)
    {
        static_assert_base(
            ProcessModel,
            StationaryProcessModel<State, Input>);

        static_assert_base(
            ProcessModel,
            GaussianMap<State, Noise>);

        static_assert_base(
            ObservationModel,
            RaoBlackwellObservationModel<State, Observation>);

        SamplingBlocks(sampling_blocks);
    }

    virtual ~RaoBlackwellCoordinateParticleFilter() { }

public:
    void Filter(const Observation&  observation,
                const Scalar&       delta_time,
                const Input&        input)
    {
        observation_model_->SetObservation(observation, delta_time);

        loglikes_ = std::vector<Scalar>(samples_.size(), 0);
        noises_ = std::vector<Noise>(samples_.size(), Noise::Zero(process_model_->NoiseDimension()));
        next_samples_ = samples_;

        for(size_t block_index = 0; block_index < sampling_blocks_.size(); block_index++)
        {
            INIT_PROFILING;
            for(size_t particle_index = 0; particle_index < samples_.size(); particle_index++)
            {
                for(size_t i = 0; i < sampling_blocks_[block_index].size(); i++)
                    noises_[particle_index](sampling_blocks_[block_index][i]) = unit_gaussian_.Sample()(0);
            }
            MEASURE("sampling");
            for(size_t particle_index = 0; particle_index < samples_.size(); particle_index++)
            {
                process_model_->Condition(delta_time,
                                          samples_[particle_index],
                                          input);

                next_samples_[particle_index] = process_model_->MapStandardGaussian(noises_[particle_index]);
            }
            MEASURE("propagation");

            bool update_occlusions = (block_index == sampling_blocks_.size()-1);
            std::vector<Scalar> new_loglikes = observation_model_->Loglikes(next_samples_,
                                                                           indices_,
                                                                           update_occlusions);
            MEASURE("evaluation");
            std::vector<Scalar> delta_loglikes(new_loglikes.size());
            for(size_t i = 0; i < delta_loglikes.size(); i++)
                delta_loglikes[i] = new_loglikes[i] - loglikes_[i];
            loglikes_ = new_loglikes;
            UpdateWeights(delta_loglikes);
            MEASURE("updating weights");

        }

        samples_ = next_samples_;
        state_distribution_.SetDeltas(samples_); // not sure whether this is the right place

    }

    void Resample(const size_t& sample_count)
    {
        std::vector<State> samples(sample_count);
        std::vector<size_t> indices(sample_count);
        std::vector<Noise> noises(sample_count);
        std::vector<State> next_samples(sample_count);
        std::vector<Scalar> loglikes(sample_count);

        fl::hf::DiscreteSampler sampler(log_weights_);

        for(size_t i = 0; i < sample_count; i++)
        {
            size_t index = sampler.Sample();

            samples[i]      = samples_[index];
            indices[i]      = indices_[index];
            noises[i]       = noises_[index];
            next_samples[i] = next_samples_[index];
            loglikes[i]     = loglikes_[index];
        }
        samples_        = samples;
        indices_        = indices;
        noises_         = noises;
        next_samples_   = next_samples;
        loglikes_       = loglikes;

        log_weights_        = std::vector<Scalar>(samples_.size(), 0.);

        state_distribution_.SetDeltas(samples_); // not sure whether this is the right place
    }

private:
    void UpdateWeights(std::vector<Scalar> log_weight_diffs)
    {
        for(size_t i = 0; i < log_weight_diffs.size(); i++)
            log_weights_[i] += log_weight_diffs[i];

        std::vector<Scalar> weights = log_weights_;
        fl::hf::Sort(weights, 1);

        for(int i = weights.size() - 1; i >= 0; i--)
            weights[i] -= weights[0];

        weights = fl::hf::Apply<Scalar, Scalar>(weights, std::exp);
        weights = fl::hf::SetSum(weights, Scalar(1));

        // compute KL divergence to uniform distribution KL(p|u)
        Scalar kl_divergence = std::log(Scalar(weights.size()));
        for(size_t i = 0; i < weights.size(); i++)
        {
            Scalar information = - std::log(weights[i]) * weights[i];
            if(!std::isfinite(information))
                information = 0; // the limit for weight -> 0 is equal to 0
            kl_divergence -= information;
        }

        if(kl_divergence > max_kl_divergence_)
            Resample(samples_.size());
    }

public:
    // set
    void Samples(const std::vector<State >& samples)
    {
        samples_ = samples;
        indices_ = std::vector<size_t>(samples_.size(), 0); observation_model_->Reset();
        log_weights_ = std::vector<Scalar>(samples_.size(), 0);
    }
    void SamplingBlocks(const std::vector<std::vector<size_t>>& sampling_blocks)
    {
        sampling_blocks_ = sampling_blocks;

        // make sure sizes are consistent
        size_t dimension = 0;
        for(size_t i = 0; i < sampling_blocks_.size(); i++)
            for(size_t j = 0; j < sampling_blocks_[i].size(); j++)
                dimension++;

        if(dimension != process_model_->NoiseDimension())
        {
            std::cout << "the dimension of the sampling blocks is " << dimension
                      << " while the dimension of the noise is "
                      << process_model_->NoiseDimension() << std::endl;
            exit(-1);
        }
    }

    // get
    const std::vector<State>& Samples() const
    {
        return samples_;
    }

    StateDistributionType& StateDistribution()
    {
        return state_distribution_;
    }

private:
    // internal state TODO: THIS COULD BE MADE MORE COMPACT!!
    StateDistributionType state_distribution_;

    std::vector<State > samples_;
    std::vector<size_t> indices_;
    std::vector<Scalar>  log_weights_;
    std::vector<Noise> noises_;
    std::vector<State> next_samples_;
    std::vector<Scalar> loglikes_;

    // observation model
    boost::shared_ptr<ObservationModel> observation_model_;

    // process model
    boost::shared_ptr<ProcessModel> process_model_;

    // parameters
    std::vector<std::vector<size_t>> sampling_blocks_;
    Scalar max_kl_divergence_;

    // distribution for sampling
    Gaussian<Eigen::Matrix<Scalar,1,1>> unit_gaussian_;
};

}

#endif
<|endoftext|>


<commit_before>/*
 * Copyright 2015 Nicolas Pope
 */

#ifndef DHARC_NODE_HPP_
#define DHARC_NODE_HPP_

#include <ostream>
#include <istream>
#include <string>
#include <cstdint>

#include "dharc/rpc_packer.hpp"

namespace dharc {

static_assert(sizeof(double) <= 64, "Double is too big");

/* Constants for special node types */
enum {
	kNullNode = 0,
	kTrueNode = 1,
	kFalseNode = 2
};

/**
 * Node Identifier, Plain Old Data type.
 *     Represents a concept and point in the dharc hypergraph. Two Nodes
 *     together identify an arc in the hypergraph. Any raw data type can
 *     be represented by a corresponding Node and Nodes can be compared with
 *     each other.
 */
struct Node {
	enum struct Type : uint8_t {
		special,
		integer,
		real,
		character,
		constant,
		allocated,
	};

	Type t;
	union {
	uint64_t ui;
	int64_t i;
	double d;
	char c;
	};

	/* Type casting to a Node */
	Node() = default;
	constexpr Node(Type type, int64_t value) : t(type), i(value) {}
	explicit constexpr Node(int value) : t(Type::integer), i(value) {}
	explicit constexpr Node(float value) : t(Type::real), d(value) {}
	explicit constexpr Node(double value) : t(Type::real), d(value) {}
	explicit constexpr Node(char value) : t(Type::character), c(value) {}
	explicit constexpr Node(bool value)
		: t(Type::special), i((value) ? kTrueNode : kFalseNode) {}

	/**
	 * Generate a Node from a string.
	 *     The string must be a valid format or the null Node is returned.
	 *     Integers (Base 10), floating point numbers, characters expressed as
	 *     'a', the keywords "true", "false and "null" are all valid. Raw Node
	 *     strings of the form "[<type>:<number>]" are also accepted.
	 *
	 * @param str Valid node string.
	 * @return null Node or Node form the string.
	 */
	explicit Node(const std::string &str);

	/** Same as for Node(const std::string &str); */
	explicit Node(const char *str);

	/* Type casting from a Node */
	explicit operator int() const;
	explicit operator float() const;
	explicit operator double() const;
	explicit operator char() const;
	explicit operator bool() const;

	/**
	 * Convert the Node to a string object.
	 *     Special types are converted to corresponding words and numeric types
	 *     are converted to standard base 10 string form. Other kinds of Node
	 *     are shown as <type>:<number>. Calling fromString on the returned
	 *     string is guaranteed to reproduce the same Node.
	 *
	 * @return String representation of the node.
	 */
	explicit operator std::string() const;
};

/**
 * Integer NID literals.
 * e.g. Nid x = 1234_n;
 */
constexpr Node operator"" _n(unsigned long long value) {
	return Node(static_cast<int>(value));
}

/**
 * Real NID literals.
 * e.g. Nid x = 12.34_n;
 */
constexpr Node operator"" _n(long double value) {
	return Node(static_cast<double>(value));
}

/**
 * Character NID literals.
 * e.g. Nid x = 'a'_n;
 */
constexpr Node operator"" _n(char value) {
	return Node(Node::Type::character, value);
}

/* Special node constants */
constexpr Node null_n = Node(Node::Type::special, kNullNode);
constexpr Node true_n = Node(Node::Type::special, kTrueNode);
constexpr Node false_n = Node(Node::Type::special, kFalseNode);

/* Relational operators */
constexpr bool operator==(const Node &a, const Node &b) {
	return a.t == b.t && a.i == b.i;
}

constexpr bool operator!=(const Node &a, const Node &b) {
	return a.t != b.t || a.i != b.i;
}

constexpr bool operator<(const Node &a, const Node &b) {
	return a.t < b.t || (a.t == b.t && a.i < b.i);
}

constexpr bool operator>(const Node &a, const Node &b) {
	return a.t > b.t || (a.t == b.t && a.i > b.i);
}

constexpr bool operator<=(const Node &a, const Node &b) {
	return a.t <= b.t || (a.t == b.t && a.i <= b.i);
}

constexpr bool operator>=(const Node &a, const Node &b) {
	return a.t >= b.t || (a.t == b.t && a.i >= b.i);
}

/* Stream Operators */
std::ostream &operator<<(std::ostream &os, const Node &n);
std::istream &operator>>(std::istream &is, Node &n);

/* Pack and unpack for remote procedure call */
namespace rpc {
template <>
struct Packer<Node> {
	static void pack(std::ostream &os, const Node &n);
	static Node unpack(std::istream &is);
};
};  // namespace rpc
};  // namespace dharc

#endif  // DHARC_NODE_HPP_
<commit_msg>Fixed uninitialized node components bug<commit_after>/*
 * Copyright 2015 Nicolas Pope
 */

#ifndef DHARC_NODE_HPP_
#define DHARC_NODE_HPP_

#include <ostream>
#include <istream>
#include <string>
#include <cstdint>

#include "dharc/rpc_packer.hpp"

namespace dharc {

static_assert(sizeof(double) <= 64, "Double is too big");

/* Constants for special node types */
enum {
	kNullNode = 0,
	kTrueNode = 1,
	kFalseNode = 2
};

/**
 * Node Identifier, Plain Old Data type.
 *     Represents a concept and point in the dharc hypergraph. Two Nodes
 *     together identify an arc in the hypergraph. Any raw data type can
 *     be represented by a corresponding Node and Nodes can be compared with
 *     each other.
 */
struct Node {
	enum struct Type : uint8_t {
		special,
		integer,
		real,
		character,
		constant,
		allocated,
	};

	Type t;
	union {
	uint64_t ui;
	int64_t i;
	double d;
	char c;
	};

	/* Type casting to a Node */
	Node() = default;
	constexpr Node(Type type, int64_t value) : t(type), i(value) {}
	explicit constexpr Node(int value) : t(Type::integer), i(value) {}
	explicit constexpr Node(float value) : t(Type::real), d(value) {}
	explicit constexpr Node(double value) : t(Type::real), d(value) {}
	explicit constexpr Node(char value) : t(Type::character), i(value) {}
	explicit constexpr Node(bool value)
		: t(Type::special), i((value) ? kTrueNode : kFalseNode) {}

	/**
	 * Generate a Node from a string.
	 *     The string must be a valid format or the null Node is returned.
	 *     Integers (Base 10), floating point numbers, characters expressed as
	 *     'a', the keywords "true", "false and "null" are all valid. Raw Node
	 *     strings of the form "[<type>:<number>]" are also accepted.
	 *
	 * @param str Valid node string.
	 * @return null Node or Node form the string.
	 */
	explicit Node(const std::string &str);

	/** Same as for Node(const std::string &str); */
	explicit Node(const char *str);

	/* Type casting from a Node */
	explicit operator int() const;
	explicit operator float() const;
	explicit operator double() const;
	explicit operator char() const;
	explicit operator bool() const;

	/**
	 * Convert the Node to a string object.
	 *     Special types are converted to corresponding words and numeric types
	 *     are converted to standard base 10 string form. Other kinds of Node
	 *     are shown as <type>:<number>. Calling fromString on the returned
	 *     string is guaranteed to reproduce the same Node.
	 *
	 * @return String representation of the node.
	 */
	explicit operator std::string() const;
};

/**
 * Integer NID literals.
 * e.g. Nid x = 1234_n;
 */
constexpr Node operator"" _n(unsigned long long value) {
	return Node(static_cast<int>(value));
}

/**
 * Real NID literals.
 * e.g. Nid x = 12.34_n;
 */
constexpr Node operator"" _n(long double value) {
	return Node(static_cast<double>(value));
}

/**
 * Character NID literals.
 * e.g. Nid x = 'a'_n;
 */
constexpr Node operator"" _n(char value) {
	return Node(Node::Type::character, value);
}

/* Special node constants */
constexpr Node null_n = Node(Node::Type::special, kNullNode);
constexpr Node true_n = Node(Node::Type::special, kTrueNode);
constexpr Node false_n = Node(Node::Type::special, kFalseNode);

/* Relational operators */
constexpr bool operator==(const Node &a, const Node &b) {
	return a.t == b.t && a.i == b.i;
}

constexpr bool operator!=(const Node &a, const Node &b) {
	return a.t != b.t || a.i != b.i;
}

constexpr bool operator<(const Node &a, const Node &b) {
	return a.t < b.t || (a.t == b.t && a.i < b.i);
}

constexpr bool operator>(const Node &a, const Node &b) {
	return a.t > b.t || (a.t == b.t && a.i > b.i);
}

constexpr bool operator<=(const Node &a, const Node &b) {
	return a.t <= b.t || (a.t == b.t && a.i <= b.i);
}

constexpr bool operator>=(const Node &a, const Node &b) {
	return a.t >= b.t || (a.t == b.t && a.i >= b.i);
}

/* Stream Operators */
std::ostream &operator<<(std::ostream &os, const Node &n);
std::istream &operator>>(std::istream &is, Node &n);

/* Pack and unpack for remote procedure call */
namespace rpc {
template <>
struct Packer<Node> {
	static void pack(std::ostream &os, const Node &n);
	static Node unpack(std::istream &is);
};
};  // namespace rpc
};  // namespace dharc

#endif  // DHARC_NODE_HPP_
<|endoftext|>


<commit_before>#include "..\I<%= $cur_module.name %>.h"

#include "logging/RhoLog.h"
#undef DEFAULT_LOGCATEGORY
#define DEFAULT_LOGCATEGORY "<%= $cur_module.name %>"

#include "ruby/ext/rho/rhoruby.h"
#include "common/StringConverter.h"
#include "common/AutoPointer.h"

using namespace rho;
using namespace rho::common;

extern "C"
{

void rho_wm_impl_performOnUiThread(rho::common::IRhoRunnable* pTask);
VALUE getRuby_<%= $cur_module.name %>_Module();

<% if $cur_module.is_template_default_instance %>
VALUE rb_<%= $cur_module.name %>_s_default(VALUE klass)
{
    rho::StringW strDefaultID = C<%= $cur_module.name %>FactoryBase::get<%= $cur_module.name %>SingletonS()->getDefaultID();

    return rho_ruby_create_object_with_id( klass, convertToStringA(strDefaultID).c_str() );
}

VALUE rb_<%= $cur_module.name %>_s_set_default(VALUE klass, VALUE valObj)
{
    const char* szID = rho_ruby_get_object_id( valObj );
    C<%= $cur_module.name %>FactoryBase::get<%= $cur_module.name %>SingletonS()->setDefaultID(convertToStringW(szID));

    return rho_ruby_get_NIL();
}
<% end %>

extern "C" static void
string_iter(const char* szVal, void* par)
{
    rho::Vector<rho::StringW>& ar = *((rho::Vector<rho::StringW>*)(par));
    ar.addElement( convertToStringW(szVal) );
}

static void getStringArrayFromValue(VALUE val, rho::Vector<rho::StringW>& res)
{
    rho_ruby_enum_strary(val, string_iter, &res);
}

extern "C" static void hash_eachstr(const char* szName, const char* szVal, void* par)
{
    rho::Hashtable<rho::StringW, rho::StringW>& hash = *((rho::Hashtable<rho::StringW, rho::StringW>*)(par));
    hash.put( convertToStringW(szName), convertToStringW(szVal) );
}

static void getStringHashFromValue(VALUE val, rho::Hashtable<rho::StringW, rho::StringW>& res)
{
    rho_ruby_enum_strhash(val, hash_eachstr, &res);
}

//Module instance methods
<% $cur_module.methods.each do |module_method| %>
<% if module_method.access == ModuleMethod::ACCESS_STATIC %>
<%= api_generator_MakeRubyMethodDecl($cur_module.name, module_method, true)%>
<% else %>
static VALUE _api_generator_<%= $cur_module.name %>_<%= module_method.name %>(int argc, VALUE *argv, I<%= $cur_module.name %>* pObj)
<% end %>
{
    CMethodResult oRes;

<% if module_method.is_factory_method %>
    oRes.setRubyObjectClass(getRuby_<%= $cur_module.name %>_Module());
<% end %>

    rho::common::IRhoRunnable* pFunctor = 0;
    bool bUseCallback = false;
    int nCallbackArg = 0;

<% functor_params = ""; first_arg = 0; %>
<% module_method.params.each do |param| %>

    nCallbackArg = <%= first_arg + 1 %>;

    <% if !param.can_be_nil %>
    if ( argc == <%= first_arg %> )
    {
        oRes.setArgError(L"Wrong number of arguments: " + convertToStringW(argc) + L" instead of " + convertToStringW(<%= module_method.params.size() %>) );
        return oRes.toRuby();
    }
    <% end %>

<% if param.type == MethodParam::TYPE_STRING %>
    <%= api_generator_cpp_makeNativeType(param.type) %> arg<%= first_arg %>;
    if ( argc > <%= first_arg %> )
    {
        if ( rho_ruby_is_string(argv[<%= first_arg %>]) )
        {
            arg<%= first_arg %> = convertToStringW(getStringFromValue(argv[<%= first_arg %>]));
<% if first_arg == 0 %>
            oRes.setStringParam(getStringFromValue(argv[<%= first_arg %>]));
<% end %>
        }
        else if (!rho_ruby_is_NIL(argv[<%= first_arg %>]))
        {
            oRes.setArgError(L"Type error: argument " L<%= "\"#{first_arg}\"" %> L" should be " L<%= "\"#{param.type.downcase}\"" %> );
            return oRes.toRuby();
        }
    }
<% end %>

<% if param.type == MethodParam::TYPE_ARRAY %>
    <%= api_generator_cpp_makeNativeType(param.type) %> arg<%= first_arg %>;
    if ( argc > <%= first_arg %> )
    {
        if ( rho_ruby_is_array(argv[<%= first_arg %>]) )
            getStringArrayFromValue(argv[<%= first_arg %>], arg<%= first_arg %>);
        else if (!rho_ruby_is_NIL(argv[<%= first_arg %>]))
        {
            oRes.setArgError(L"Type error: argument " L<%= "\"#{first_arg}\"" %> L" should be " L<%= "\"#{param.type.downcase}\"" %> );
            return oRes.toRuby();
        }
    }
<% end %>

<% if param.type == MethodParam::TYPE_HASH %>
    <%= api_generator_cpp_makeNativeType(param.type) %> arg<%= first_arg %>;
    if ( argc > <%= first_arg %> )
    {
        if ( rho_ruby_is_hash(argv[<%= first_arg %>]) )
            getStringHashFromValue(argv[<%= first_arg %>], arg<%= first_arg %>);
        else if (!rho_ruby_is_NIL(argv[<%= first_arg %>]))
        {
            oRes.setArgError(L"Type error: argument " L<%= "\"#{first_arg}\"" %> L" should be " L<%= "\"#{param.type.downcase}\"" %> );
            return oRes.toRuby();
        }
    }
<% end %>

<% functor_params += "arg#{first_arg}, " %>
<% first_arg = first_arg+1 %>
<% end %>

    if ( argc > nCallbackArg )
    {
<% if module_method.has_callback == ModuleMethod::CALLBACK_NONE %>
        oRes.setArgError(L"Wrong number of arguments: " + convertToStringW(argc) + L" instead of " + convertToStringW(<%= module_method.params.size() %>) );
        return oRes.toRuby();
<% end %>

        if ( !rho_ruby_is_string(argv[nCallbackArg]) )
        {
            oRes.setArgError(L"Type error: callback should be String");
            return oRes.toRuby();
        }

        oRes.setCallInUIThread(<%= module_method.is_run_in_ui_thread ? "true" : "false" %>);
        oRes.setRubyCallback( getStringFromValue(argv[nCallbackArg]) );
        if ( argc > nCallbackArg + 1 )
        {
            if ( !rho_ruby_is_string(argv[nCallbackArg + 1]) )
            {
                oRes.setArgError(L"Type error: callback parameter should be String");
                return oRes.toRuby();
            }

            oRes.setCallbackParam( getStringFromValue(argv[nCallbackArg + 1]) );
        }

    }

<% if module_method.access != ModuleMethod::ACCESS_STATIC %>
    pFunctor = rho_makeInstanceClassFunctor<%= module_method.params.size()+1%>( pObj, &I<%= $cur_module.name %>::<%= module_method.name %>, <%= functor_params %> oRes );
<% else %>
    pFunctor = rho_makeInstanceClassFunctor<%= module_method.params.size()+1%>( C<%= $cur_module.name %>FactoryBase::get<%= $cur_module.name %>SingletonS(), &I<%= $cur_module.name %>Singleton::<%= module_method.name %>, <%= functor_params %> oRes );
<% end %>

<% if module_method.is_run_in_ui_thread %>
    rho_wm_impl_performOnUiThread( pFunctor );
<% elsif module_method.is_run_in_thread %>
    C<%= $cur_module.name %>FactoryBase::get<%= $cur_module.name %>SingletonS()->addCommandToQueue( pFunctor );
<% else %>

    if ( bUseCallback )
        C<%= $cur_module.name %>FactoryBase::get<%= $cur_module.name %>SingletonS()->addCommandToQueue( pFunctor );
    else
    {
        delete pFunctor;

<% if module_method.access != ModuleMethod::ACCESS_STATIC %>
        pObj-><%= module_method.name %>( <%= functor_params %> oRes );
<% else %>
        C<%= $cur_module.name %>FactoryBase::get<%= $cur_module.name %>SingletonS()-><%= module_method.name %>( <%= functor_params %> oRes );
<% end %>

    }
<% end %>

    return oRes.toRuby();
}

<% if module_method.access != ModuleMethod::ACCESS_STATIC %>
<%= api_generator_MakeRubyMethodDecl($cur_module.name, module_method, module_method.access == ModuleMethod::ACCESS_STATIC)%>
{
    const char* szID = rho_ruby_get_object_id( obj );
    I<%= $cur_module.name %>* pObj =  C<%= $cur_module.name %>FactoryBase::getInstance()->getModuleByID(convertToStringW(szID));

    return _api_generator_<%= $cur_module.name %>_<%= module_method.name %>(argc, argv, pObj);
}
<% end %>

<% if $cur_module.is_template_default_instance && module_method.access == ModuleMethod::ACCESS_INSTANCE%>
<%= api_generator_MakeRubyMethodDecl($cur_module.name + "_def", module_method, true)%>
{
    rho::StringW strDefaultID = C<%= $cur_module.name %>FactoryBase::get<%= $cur_module.name %>SingletonS()->getDefaultID();
    I<%= $cur_module.name %>* pObj = C<%= $cur_module.name %>FactoryBase::getInstance()->getModuleByID(strDefaultID);

    return _api_generator_<%= $cur_module.name %>_<%= module_method.name %>(argc, argv, pObj);
}
<% end %>
<% end %>

}<commit_msg>api_generator:cpp: fix ruby wrap<commit_after>#include "..\I<%= $cur_module.name %>.h"

#include "logging/RhoLog.h"
#undef DEFAULT_LOGCATEGORY
#define DEFAULT_LOGCATEGORY "<%= $cur_module.name %>"

#include "ruby/ext/rho/rhoruby.h"
#include "common/StringConverter.h"
#include "common/AutoPointer.h"

using namespace rho;
using namespace rho::common;

extern "C"
{

void rho_wm_impl_performOnUiThread(rho::common::IRhoRunnable* pTask);
VALUE getRuby_<%= $cur_module.name %>_Module();

<% if $cur_module.is_template_default_instance %>
VALUE rb_<%= $cur_module.name %>_s_default(VALUE klass)
{
    rho::StringW strDefaultID = C<%= $cur_module.name %>FactoryBase::get<%= $cur_module.name %>SingletonS()->getDefaultID();

    return rho_ruby_create_object_with_id( klass, convertToStringA(strDefaultID).c_str() );
}

VALUE rb_<%= $cur_module.name %>_s_setDefault(VALUE klass, VALUE valObj)
{
    const char* szID = rho_ruby_get_object_id( valObj );
    C<%= $cur_module.name %>FactoryBase::get<%= $cur_module.name %>SingletonS()->setDefaultID(convertToStringW(szID));

    return rho_ruby_get_NIL();
}
<% end %>

extern "C" static void
string_iter(const char* szVal, void* par)
{
    rho::Vector<rho::StringW>& ar = *((rho::Vector<rho::StringW>*)(par));
    ar.addElement( convertToStringW(szVal) );
}

static void getStringArrayFromValue(VALUE val, rho::Vector<rho::StringW>& res)
{
    rho_ruby_enum_strary(val, string_iter, &res);
}

extern "C" static void hash_eachstr(const char* szName, const char* szVal, void* par)
{
    rho::Hashtable<rho::StringW, rho::StringW>& hash = *((rho::Hashtable<rho::StringW, rho::StringW>*)(par));
    hash.put( convertToStringW(szName), convertToStringW(szVal) );
}

static void getStringHashFromValue(VALUE val, rho::Hashtable<rho::StringW, rho::StringW>& res)
{
    rho_ruby_enum_strhash(val, hash_eachstr, &res);
}

//Module instance methods
<% $cur_module.methods.each do |module_method| %>
<% if module_method.access == ModuleMethod::ACCESS_STATIC %>
<%= api_generator_MakeRubyMethodDecl($cur_module.name, module_method, true)%>
<% else %>
static VALUE _api_generator_<%= $cur_module.name %>_<%= module_method.name %>(int argc, VALUE *argv, I<%= $cur_module.name %>* pObj)
<% end %>
{
    CMethodResult oRes;

<% if module_method.is_factory_method %>
    oRes.setRubyObjectClass(getRuby_<%= $cur_module.name %>_Module());
<% end %>

    rho::common::IRhoRunnable* pFunctor = 0;
    bool bUseCallback = false;
    int nCallbackArg = 0;

<% functor_params = ""; first_arg = 0; %>
<% module_method.params.each do |param| %>

    nCallbackArg = <%= first_arg + 1 %>;

    <% if !param.can_be_nil %>
    if ( argc == <%= first_arg %> )
    {
        oRes.setArgError(L"Wrong number of arguments: " + convertToStringW(argc) + L" instead of " + convertToStringW(<%= module_method.params.size() %>) );
        return oRes.toRuby();
    }
    <% end %>

<% if param.type == MethodParam::TYPE_STRING %>
    <%= api_generator_cpp_makeNativeType(param.type) %> arg<%= first_arg %>;
    if ( argc > <%= first_arg %> )
    {
        if ( rho_ruby_is_string(argv[<%= first_arg %>]) )
        {
            arg<%= first_arg %> = convertToStringW(getStringFromValue(argv[<%= first_arg %>]));
<% if first_arg == 0 %>
            oRes.setStringParam(getStringFromValue(argv[<%= first_arg %>]));
<% end %>
        }
        else if (!rho_ruby_is_NIL(argv[<%= first_arg %>]))
        {
            oRes.setArgError(L"Type error: argument " L<%= "\"#{first_arg}\"" %> L" should be " L<%= "\"#{param.type.downcase}\"" %> );
            return oRes.toRuby();
        }
    }
<% end %>

<% if param.type == MethodParam::TYPE_ARRAY %>
    <%= api_generator_cpp_makeNativeType(param.type) %> arg<%= first_arg %>;
    if ( argc > <%= first_arg %> )
    {
        if ( rho_ruby_is_array(argv[<%= first_arg %>]) )
            getStringArrayFromValue(argv[<%= first_arg %>], arg<%= first_arg %>);
        else if (!rho_ruby_is_NIL(argv[<%= first_arg %>]))
        {
            oRes.setArgError(L"Type error: argument " L<%= "\"#{first_arg}\"" %> L" should be " L<%= "\"#{param.type.downcase}\"" %> );
            return oRes.toRuby();
        }
    }
<% end %>

<% if param.type == MethodParam::TYPE_HASH %>
    <%= api_generator_cpp_makeNativeType(param.type) %> arg<%= first_arg %>;
    if ( argc > <%= first_arg %> )
    {
        if ( rho_ruby_is_hash(argv[<%= first_arg %>]) )
            getStringHashFromValue(argv[<%= first_arg %>], arg<%= first_arg %>);
        else if (!rho_ruby_is_NIL(argv[<%= first_arg %>]))
        {
            oRes.setArgError(L"Type error: argument " L<%= "\"#{first_arg}\"" %> L" should be " L<%= "\"#{param.type.downcase}\"" %> );
            return oRes.toRuby();
        }
    }
<% end %>

<% functor_params += "arg#{first_arg}, " %>
<% first_arg = first_arg+1 %>
<% end %>

    if ( argc > nCallbackArg )
    {
<% if module_method.has_callback == ModuleMethod::CALLBACK_NONE %>
        oRes.setArgError(L"Wrong number of arguments: " + convertToStringW(argc) + L" instead of " + convertToStringW(<%= module_method.params.size() %>) );
        return oRes.toRuby();
<% end %>

        if ( !rho_ruby_is_string(argv[nCallbackArg]) )
        {
            oRes.setArgError(L"Type error: callback should be String");
            return oRes.toRuby();
        }

        oRes.setCallInUIThread(<%= module_method.is_run_in_ui_thread ? "true" : "false" %>);
        oRes.setRubyCallback( getStringFromValue(argv[nCallbackArg]) );
        if ( argc > nCallbackArg + 1 )
        {
            if ( !rho_ruby_is_string(argv[nCallbackArg + 1]) )
            {
                oRes.setArgError(L"Type error: callback parameter should be String");
                return oRes.toRuby();
            }

            oRes.setCallbackParam( getStringFromValue(argv[nCallbackArg + 1]) );
        }

    }

<% if module_method.access != ModuleMethod::ACCESS_STATIC %>
    pFunctor = rho_makeInstanceClassFunctor<%= module_method.params.size()+1%>( pObj, &I<%= $cur_module.name %>::<%= module_method.name %>, <%= functor_params %> oRes );
<% else %>
    pFunctor = rho_makeInstanceClassFunctor<%= module_method.params.size()+1%>( C<%= $cur_module.name %>FactoryBase::get<%= $cur_module.name %>SingletonS(), &I<%= $cur_module.name %>Singleton::<%= module_method.name %>, <%= functor_params %> oRes );
<% end %>

<% if module_method.is_run_in_ui_thread %>
    rho_wm_impl_performOnUiThread( pFunctor );
<% elsif module_method.is_run_in_thread %>
    C<%= $cur_module.name %>FactoryBase::get<%= $cur_module.name %>SingletonS()->addCommandToQueue( pFunctor );
<% else %>

    if ( bUseCallback )
        C<%= $cur_module.name %>FactoryBase::get<%= $cur_module.name %>SingletonS()->addCommandToQueue( pFunctor );
    else
    {
        delete pFunctor;

<% if module_method.access != ModuleMethod::ACCESS_STATIC %>
        pObj-><%= module_method.name %>( <%= functor_params %> oRes );
<% else %>
        C<%= $cur_module.name %>FactoryBase::get<%= $cur_module.name %>SingletonS()-><%= module_method.name %>( <%= functor_params %> oRes );
<% end %>

    }
<% end %>

    return oRes.toRuby();
}

<% if module_method.access != ModuleMethod::ACCESS_STATIC %>
<%= api_generator_MakeRubyMethodDecl($cur_module.name, module_method, module_method.access == ModuleMethod::ACCESS_STATIC)%>
{
    const char* szID = rho_ruby_get_object_id( obj );
    I<%= $cur_module.name %>* pObj =  C<%= $cur_module.name %>FactoryBase::getInstance()->getModuleByID(convertToStringW(szID));

    return _api_generator_<%= $cur_module.name %>_<%= module_method.name %>(argc, argv, pObj);
}
<% end %>

<% if $cur_module.is_template_default_instance && module_method.access == ModuleMethod::ACCESS_INSTANCE%>
<%= api_generator_MakeRubyMethodDecl($cur_module.name + "_def", module_method, true)%>
{
    rho::StringW strDefaultID = C<%= $cur_module.name %>FactoryBase::get<%= $cur_module.name %>SingletonS()->getDefaultID();
    I<%= $cur_module.name %>* pObj = C<%= $cur_module.name %>FactoryBase::getInstance()->getModuleByID(strDefaultID);

    return _api_generator_<%= $cur_module.name %>_<%= module_method.name %>(argc, argv, pObj);
}
<% end %>
<% end %>

}<|endoftext|>


<commit_before>#ifndef GENERIC_CIFY_HPP
# define GENERIC_CIFY_HPP
# pragma once

#include <utility>

namespace generic
{

namespace
{

//////////////////////////////////////////////////////////////////////////////
template <typename F, int I, typename L, typename R, typename ...A>
inline F cify(L&& l, R (*)(A...) noexcept(noexcept(
  ::std::declval<F>()(::std::declval<A>()...))))
{
  static L l_(::std::forward<L>(l));
  static bool full;

  if (full)
  {
    l_.~L();

    new (static_cast<void*>(&l_)) L(::std::forward<L>(l));
  }
  else
  {
    full = true;
  }

  struct S
  {
    static R f(A... args) noexcept(noexcept(
      ::std::declval<F>()(::std::forward<A>(args)...)))
    {
      return l_(::std::forward<A>(args)...);
    }
  };

  return &S::f;
}

//////////////////////////////////////////////////////////////////////////////
template <typename F, int I, typename L, typename R, typename ...A>
inline F thread_local_cify(L&& l, R (*)(A...) noexcept(noexcept(
  ::std::declval<F>()(::std::declval<A>()...))))
{
  static thread_local L l_(::std::forward<L>(l));
  static thread_local bool full;

  if (full)
  {
    l_.~L();

    new (static_cast<void*>(&l_)) L(::std::forward<L>(l));
  }
  else
  {
    full = true;
  }

  struct S
  {
    static R f(A... args) noexcept(noexcept(
      ::std::declval<F>()(::std::forward<A>(args)...)))
    {
      return l_(::std::forward<A>(args)...);
    }
  };

  return &S::f;
}

}

//////////////////////////////////////////////////////////////////////////////
template <typename F, int I = 0, typename L>
inline F cify(L&& l)
{
  return cify<F, I>(::std::forward<L>(l), F());
}

//////////////////////////////////////////////////////////////////////////////
template <typename F, int I = 0, typename L>
inline F thread_local_cify(L&& l)
{
  return thread_local_cify<F, I>(::std::forward<L>(l), F());
}

}

#endif // GENERIC_CIFY_HPP
<commit_msg>some fixes<commit_after>#ifndef GENERIC_CIFY_HPP
# define GENERIC_CIFY_HPP
# pragma once

#include <utility>

namespace generic
{

namespace
{

//////////////////////////////////////////////////////////////////////////////
template <typename F, int I, typename L, typename R, typename ...A>
inline F cify(L&& l, R (*)(A...) noexcept(noexcept(
  ::std::declval<F>()(::std::declval<A>()...))))
{
  static L l_(::std::forward<L>(l));
  static bool full;

  if (full)
  {
    l_.~L();

    new (static_cast<void*>(&l_)) L(::std::forward<L>(l));
  }
  else
  {
    full = true;
  }

  return +[](A... args) noexcept(noexcept(
      ::std::declval<F>()(::std::forward<A>(args)...)))
    {
      return l_(::std::forward<A>(args)...);
    };
}

//////////////////////////////////////////////////////////////////////////////
template <typename F, int I, typename L, typename R, typename ...A>
inline F thread_local_cify(L&& l, R (*)(A...) noexcept(noexcept(
  ::std::declval<F>()(::std::declval<A>()...))))
{
  static thread_local L l_(::std::forward<L>(l));
  static thread_local bool full;

  if (full)
  {
    l_.~L();

    new (static_cast<void*>(&l_)) L(::std::forward<L>(l));
  }
  else
  {
    full = true;
  }

  return +[](A... args) noexcept(noexcept(
      ::std::declval<F>()(::std::forward<A>(args)...)))
    {
      return l_(::std::forward<A>(args)...);
    };
}

}

//////////////////////////////////////////////////////////////////////////////
template <typename F, int I = 0, typename L>
inline F cify(L&& l)
{
  return cify<F, I>(::std::forward<L>(l), F());
}

//////////////////////////////////////////////////////////////////////////////
template <typename F, int I = 0, typename L>
inline F thread_local_cify(L&& l)
{
  return thread_local_cify<F, I>(::std::forward<L>(l), F());
}

}

#endif // GENERIC_CIFY_HPP
<|endoftext|>


<commit_before>/******************************************************************************
 *                    _   _____   __________                                  *
 *                   | | / / _ | / __/_  __/     Visibility                   *
 *                   | |/ / __ |_\ \  / /          Across                     *
 *                   |___/_/ |_/___/ /_/       Space and Time                 *
 *                                                                            *
 * This file is part of VAST. It is subject to the license terms in the       *
 * LICENSE file found in the top-level directory of this distribution and at  *
 * http://vast.io/license. No part of VAST, including this file, may be       *
 * copied, modified, propagated, or distributed except according to the terms *
 * contained in the LICENSE file.                                             *
 ******************************************************************************/

#include <caf/make_counted.hpp>

#include "vast/bitmap_algorithms.hpp"
#include "vast/error.hpp"
#include "vast/event.hpp"
#include "vast/ids.hpp"
#include "vast/load.hpp"
#include "vast/logger.hpp"
#include "vast/save.hpp"
#include "vast/segment_store.hpp"

#include "vast/concept/printable/to_string.hpp"
#include "vast/concept/printable/vast/error.hpp"
#include "vast/concept/printable/vast/filesystem.hpp"
#include "vast/concept/printable/vast/uuid.hpp"

#include "vast/const_table_slice_handle.hpp"
#include "vast/segment_store.hpp"
#include "vast/table_slice.hpp"
#include "vast/to_events.hpp"

namespace vast {

segment_store_ptr segment_store::make(caf::actor_system& sys, path dir,
                                      size_t max_segment_size,
                                      size_t in_memory_segments) {
  VAST_ASSERT(max_segment_size > 0);
  auto x = caf::make_counted<segment_store>(
    sys, std::move(dir), max_segment_size, in_memory_segments);
  // Materialize meta data of existing segments.
  if (exists(x->meta_path()))
    if (auto result = load(x->meta_path(), x->segments_); !result) {
      VAST_ERROR("failed to unarchive meta data:", to_string(result.error()));
      return nullptr;
    }
  return x;
}

segment_store::~segment_store() {
  // nop
}

caf::error segment_store::put(const_table_slice_handle xs) {
  if (auto error = builder_.add(xs))
    return error;
  if (!segments_.inject(xs->offset(), xs->offset() + xs->rows(), builder_.id()))
    return make_error(ec::unspecified, "failed to update range_map");
  if (builder_.table_slice_bytes() < max_segment_size_)
    return caf::none;
  // We have exceeded our maximum segment size and now finish
  auto x = builder_.finish();
  if (!x)
    return x.error();
  auto seg_ptr = *x;
  if (!exists(segment_path()))
    if (auto result = mkdir(segment_path()); !result)
      return result.error();
  auto filename = segment_path() / to_string(seg_ptr->id());
  if (auto result = save(filename, seg_ptr); !result)
    return result.error();
  VAST_DEBUG("wrote new segment to", filename.trim(-3));
  // Keep new segment in the cache.
  cache_.emplace(seg_ptr->id(), seg_ptr);
  return flush();
}

caf::error segment_store::flush() {
  auto result = save(meta_path(), segments_);
  return result ? caf::none : result.error();
}

caf::expected<std::vector<const_table_slice_handle>>
segment_store::get(const ids& xs) {
  // Collect candidate segments by seeking through the ID set and
  // probing each ID interval.
  std::vector<const uuid*> candidates;
  auto f = [](auto x) { return std::pair{x.left, x.right}; };
  auto g = [&](auto x) {
    auto ptr = &x.value;
    if (candidates.empty() || candidates.back() != ptr)
      candidates.push_back(ptr);
    return caf::none;
  };
  auto begin = segments_.begin();
  auto end = segments_.end();
  if (auto error = traverse(xs, begin, end, f, g))
    return error;
  // Process candidates in reverse order for maximum LRU cache hits.
  std::vector<const_table_slice_handle> result;
  VAST_DEBUG("processing", candidates.size(), "candidates");
  for (auto cand = candidates.rbegin(); cand != candidates.rend(); ++cand) {
    auto& id = **cand;
    caf::expected<std::vector<const_table_slice_handle>> slices{caf::no_error};
    if (id == builder_.id()) {
      VAST_DEBUG("looking into builder");
      slices = builder_.lookup(xs);
    } else {
      segment_ptr seg_ptr = nullptr;
      auto i = cache_.find(id);
      if (i != cache_.end()) {
        VAST_DEBUG("got cache hit for segment", id);
        seg_ptr = i->second;
      } else {
        VAST_DEBUG("got cache miss for segment", id);
        if (auto res = load(segment_path() / to_string(id), seg_ptr); !res)
          return res.error();
        i = cache_.emplace(id, seg_ptr).first;
      }
      VAST_ASSERT(seg_ptr != nullptr);
      slices = seg_ptr->lookup(xs);
    }
    if (!slices)
      return slices.error();
    result.reserve(result.size() + slices->size());
    result.insert(result.end(), slices->begin(), slices->end());
  }
  return result;
}

segment_store::segment_store(caf::actor_system& sys, path dir,
                             uint64_t max_segment_size, size_t in_memory_segments)
  : actor_system_{sys},
    dir_{std::move(dir)},
    max_segment_size_{max_segment_size},
    cache_{in_memory_segments},
    builder_{actor_system_} {
  // nop
}

} // namespace vast
<commit_msg>Log serialization error<commit_after>/******************************************************************************
 *                    _   _____   __________                                  *
 *                   | | / / _ | / __/_  __/     Visibility                   *
 *                   | |/ / __ |_\ \  / /          Across                     *
 *                   |___/_/ |_/___/ /_/       Space and Time                 *
 *                                                                            *
 * This file is part of VAST. It is subject to the license terms in the       *
 * LICENSE file found in the top-level directory of this distribution and at  *
 * http://vast.io/license. No part of VAST, including this file, may be       *
 * copied, modified, propagated, or distributed except according to the terms *
 * contained in the LICENSE file.                                             *
 ******************************************************************************/

#include <caf/make_counted.hpp>

#include "vast/bitmap_algorithms.hpp"
#include "vast/error.hpp"
#include "vast/event.hpp"
#include "vast/ids.hpp"
#include "vast/load.hpp"
#include "vast/logger.hpp"
#include "vast/save.hpp"
#include "vast/segment_store.hpp"

#include "vast/concept/printable/to_string.hpp"
#include "vast/concept/printable/vast/error.hpp"
#include "vast/concept/printable/vast/filesystem.hpp"
#include "vast/concept/printable/vast/uuid.hpp"

#include "vast/const_table_slice_handle.hpp"
#include "vast/segment_store.hpp"
#include "vast/table_slice.hpp"
#include "vast/to_events.hpp"

namespace vast {

segment_store_ptr segment_store::make(caf::actor_system& sys, path dir,
                                      size_t max_segment_size,
                                      size_t in_memory_segments) {
  VAST_ASSERT(max_segment_size > 0);
  auto x = caf::make_counted<segment_store>(
    sys, std::move(dir), max_segment_size, in_memory_segments);
  // Materialize meta data of existing segments.
  if (exists(x->meta_path()))
    if (auto result = load(x->meta_path(), x->segments_); !result) {
      VAST_ERROR("failed to unarchive meta data:", to_string(result.error()));
      return nullptr;
    }
  return x;
}

segment_store::~segment_store() {
  // nop
}

caf::error segment_store::put(const_table_slice_handle xs) {
  if (auto error = builder_.add(xs))
    return error;
  if (!segments_.inject(xs->offset(), xs->offset() + xs->rows(), builder_.id()))
    return make_error(ec::unspecified, "failed to update range_map");
  if (builder_.table_slice_bytes() < max_segment_size_)
    return caf::none;
  // We have exceeded our maximum segment size and now finish
  auto x = builder_.finish();
  if (!x)
    return x.error();
  auto seg_ptr = *x;
  if (!exists(segment_path()))
    if (auto result = mkdir(segment_path()); !result)
      return result.error();
  auto filename = segment_path() / to_string(seg_ptr->id());
  if (auto result = save(filename, seg_ptr); !result)
    return result.error();
  VAST_DEBUG("wrote new segment to", filename.trim(-3));
  // Keep new segment in the cache.
  cache_.emplace(seg_ptr->id(), seg_ptr);
  return flush();
}

caf::error segment_store::flush() {
  auto result = save(meta_path(), segments_);
  return result ? caf::none : result.error();
}

caf::expected<std::vector<const_table_slice_handle>>
segment_store::get(const ids& xs) {
  // Collect candidate segments by seeking through the ID set and
  // probing each ID interval.
  std::vector<const uuid*> candidates;
  auto f = [](auto x) { return std::pair{x.left, x.right}; };
  auto g = [&](auto x) {
    auto ptr = &x.value;
    if (candidates.empty() || candidates.back() != ptr)
      candidates.push_back(ptr);
    return caf::none;
  };
  auto begin = segments_.begin();
  auto end = segments_.end();
  if (auto error = traverse(xs, begin, end, f, g))
    return error;
  // Process candidates in reverse order for maximum LRU cache hits.
  std::vector<const_table_slice_handle> result;
  VAST_DEBUG("processing", candidates.size(), "candidates");
  for (auto cand = candidates.rbegin(); cand != candidates.rend(); ++cand) {
    auto& id = **cand;
    caf::expected<std::vector<const_table_slice_handle>> slices{caf::no_error};
    if (id == builder_.id()) {
      VAST_DEBUG("looking into builder");
      slices = builder_.lookup(xs);
    } else {
      segment_ptr seg_ptr = nullptr;
      auto i = cache_.find(id);
      if (i != cache_.end()) {
        VAST_DEBUG("got cache hit for segment", id);
        seg_ptr = i->second;
      } else {
        VAST_DEBUG("got cache miss for segment", id);
        if (auto res = load(segment_path() / to_string(id), seg_ptr); !res) {
          VAST_ERROR("unable to load segment:", res.error());
          return res.error();
        }
        i = cache_.emplace(id, seg_ptr).first;
      }
      VAST_ASSERT(seg_ptr != nullptr);
      slices = seg_ptr->lookup(xs);
    }
    if (!slices)
      return slices.error();
    result.reserve(result.size() + slices->size());
    result.insert(result.end(), slices->begin(), slices->end());
  }
  return result;
}

segment_store::segment_store(caf::actor_system& sys, path dir,
                             uint64_t max_segment_size, size_t in_memory_segments)
  : actor_system_{sys},
    dir_{std::move(dir)},
    max_segment_size_{max_segment_size},
    cache_{in_memory_segments},
    builder_{actor_system_} {
  // nop
}

} // namespace vast
<|endoftext|>


<commit_before>///////////////////////////////////////////////////////////////////////////////
//  Z-functions
///////////////////////////////////////////////////////////////////////////////

#include <iostream>
#include <string>
#include <vector>

using namespace std;

// z-functions: return z, z[i] is the length of the longest substring
//              starting from S[i] which is also a prefix of S

vector<int> get_ZFunction(string s){
    int len = s.length();
    vector<int> z(len);
    int L = 0, R = 0;
    for(int i = 1; i < len; i++ ){
        if (i > R){
            L = R = i;
            while (R < len && s[R-L] == s[R]) R++;
            z[i] = R - L; R--;
        } else {
            int k = i - L;
            if(z[k] < R - i + 1) z[i] = z[k];
            else {
                L = i;
                while (R < len && s[R - L] == s[R]) R++;
                z[i] = R - L; R--;
            }
        }
    }
    z[0] = len;
    return z;
}

///////////////////////////////////////////////////////////////////////////////
//  Knuth-Morris-Pratt
///////////////////////////////////////////////////////////////////////////////

/*
  Searches for the string w in the string s (of length k). Returns the
  0-based index of the first match (k if no match is found). Algorithm
  runs in O(k) time.
*/

#include <cassert>

using namespace std;
typedef vector<int> VI;

class KnuthMorrisPratt {
public:
    void build_table(string& w, VI& t){
        int sz = w.size();
        t = VI(sz);
        int i = 2, j = 0;
        t[0] = -1; t[1] = 0;
        while (i < sz) {
            if (w[i - 1] == w[j]) { t[i] = j + 1; i++; j++; }
            else if (j > 0) j = t[j];
            else { t[i] = 0; i++; }
        }
    }

    // returh the index of the first match, or the length of s if w is not found
    int KMP(string s, string w){
        int m = 0, i = 0;
        VI t;
        build_table(w, t);
        int sz_s = s.size();
        int sz_w = w.size();
        while (m+i < sz_s) {
            if (w[i] == s[m+i]) {
                i++;
                if (i == sz_w) return m;
            } else {
                m += i - t[i];
                if (i > 0) i = t[i];
            }
        }
        return s.length();
    }
};

int main(){
    KnuthMorrisPratt solve;
    assert(solve.KMP("win", "I wanna win.") == 3);
    assert(solve.KMP("I wanna win.", "win") == 8);
    return 0;
}

///////////////////////////////////////////////////////////////////////////////
//  Prefix Function
//  Given a string. Return an array of numbers,
//  where is defined as follows: it is a maximum length of the longest
//  proper suffix substring that matches the prefix (suffix own - so not
//  the entire line). In particular, the value is set equal to zero.
//  For example, the string "abcabcd" prefix function is: [1, 0, 0, 1, 2, 3, 0]
///////////////////////////////////////////////////////////////////////////////

vector<int> prefix_function (string s){
    int n = (int) s.length();
    vector<int> pi (n);
    for (int i=1; i<n; ++i){
        int j = pi[i-1];
        while (j > 0 && s[i] != s[j])
            j = pi[j-1];
        if (s[i] == s[j])  ++j;
        pi[i] = j;
    }
    return pi;
}
<commit_msg>Update StringMatching.cpp<commit_after>///////////////////////////////////////////////////////////////////////////////
//  Z-functions
///////////////////////////////////////////////////////////////////////////////

#include <iostream>
#include <string>
#include <vector>

using namespace std;

// z-functions: return z, z[i] is the length of the longest substring
//              starting from S[i] which is also a prefix of S

vector<int> get_ZFunction(string s){
    int len = s.length();
    vector<int> z(len);
    int L = 0, R = 0;
    for(int i = 1; i < len; i++ ){
        if (i > R){
            L = R = i;
            while (R < len && s[R-L] == s[R]) R++;
            z[i] = R - L; R--;
        } else {
            int k = i - L;
            if(z[k] < R - i + 1) z[i] = z[k];
            else {
                L = i;
                while (R < len && s[R - L] == s[R]) R++;
                z[i] = R - L; R--;
            }
        }
    }
    z[0] = len;
    return z;
}

///////////////////////////////////////////////////////////////////////////////
//  Knuth-Morris-Pratt
///////////////////////////////////////////////////////////////////////////////

/*
  Searches for the string key in the string s (of length k). Returns the
  0-based index of the first match (k if no match is found). Algorithm
  runs in O(k) time.
*/

#include <cassert>

using namespace std;
typedef vector<int> VI;

class KnuthMorrisPratt {
public:
    void build_table(string& key, VI& t){
        int sz = key.size();
        t = VI(sz);
        int i = 2, j = 0;
        t[0] = -1; t[1] = 0;
        while (i < sz) {
            if (key[i - 1] == key[j]) { t[i] = j + 1; i++; j++; }
            else if (j > 0) j = t[j];
            else { t[i] = 0; i++; }
        }
    }

    // return the index of the first match, or the length of s if key is not found
    int KMP(string s, string key){
        int m = 0, i = 0;
        VI t;
        build_table(key, t);
        int sz_s = s.size();
        int sz_w = key.size();
        while (m+i < sz_s) {
            if (key[i] == s[m+i]) {
                i++;
                if (i == sz_w) return m;
            } else {
                m += i - t[i];
                if (i > 0) i = t[i];
            }
        }
        return s.length();
    }
};

int main(){
    KnuthMorrisPratt solve;
    assert(solve.KMP("win", "I wanna win.") == 3);
    assert(solve.KMP("I wanna win.", "win") == 8);
    return 0;
}

///////////////////////////////////////////////////////////////////////////////
//  Prefix Function
//  Given a string. Return an array of numbers,
//  where is defined as follows: it is a maximum length of the longest
//  proper suffix substring that matches the prefix (suffix own - so not
//  the entire line). In particular, the value is set equal to zero.
//  For example, the string "abcabcd" prefix function is: [1, 0, 0, 1, 2, 3, 0]
///////////////////////////////////////////////////////////////////////////////

vector<int> prefix_function (string s){
    int n = (int) s.length();
    vector<int> pi (n);
    for (int i=1; i<n; ++i){
        int j = pi[i-1];
        while (j > 0 && s[i] != s[j])
            j = pi[j-1];
        if (s[i] == s[j])  ++j;
        pi[i] = j;
    }
    return pi;
}
<|endoftext|>


<commit_before>// C++ Actor Framework Exercices
// Christian Schirin, 2017-05-17
// Exercise 1: Polynomial Evaluator
#include <string>
#include <iostream>

#include "caf/all.hpp"

using std::endl;
using std::string;

using namespace caf;

// Type Aliases
using calc_atom = atom_constant<atom("calc")>;

behavior polynomial(std::array<double, 5> as) {
	return {
		[=](const calc_atom& _calc, const double x) -> double {
		// Evaluate the polynomial.
		// The accumulator variable
		double result = 0;
		// x^4, x^3, x^2, x^1, x^0
		double exponent = as.size() - 1; // this is at generalized as it gets, it would also work for polynomials with a degree that is not 4.
		// We are doing this with a for loop because C++11 doesn't support fold
		for (double a : as) {
			result += a * std::pow(x, exponent); //how does pow behave at x^0? // Apparently it returns 1.
			exponent -= 1;
		}
		return result;
	}
	};
}

int main() {
	// our CAF environment
	actor_system_config cfg;
	actor_system system{ cfg };

	std::array<double, 5> as;

	scoped_actor self{ system };

	// system will wait until both actors are destroyed before leaving main
	std::cout << std::pow(0, 0) << '\n';
}
<commit_msg>Polynomial Evaluator implemented.<commit_after>// C++ Actor Framework Exercices
// Christian Schirin, 2017-05-17
// Exercise 1: Polynomial Evaluator
#include <string>
#include <iostream>
#include <chrono>
#include <thread>

#include "caf/all.hpp"

using std::endl;
using std::string;

using namespace caf;

// Type Aliases
using calc_atom = atom_constant<atom("calc")>;

behavior polynomial(std::array<double, 5> as) {
	return {
		// Lambda expression, pass parameters by value
		[=](calc_atom, const double x) -> double {
		// Evaluate the polynomial.
		// The accumulator variable
		double result = 0;
		// x^4, x^3, x^2, x^1, x^0
		double exponent = as.size() - 1; // This is at generalized as it gets, it would also work for polynomials with a degree that is not 4.
		// Doing this with a for loop because C++11 doesn't support fold
		for (double a : as) {
			result += a * std::pow(x, exponent); //how does pow behave at x^0? // Apparently it returns 1.
			exponent -= 1; // We need to go from size - 1 to 0 here.
		}
		return result;
	}
	};
}

int main() {
	// our CAF environment
	actor_system_config cfg;
	actor_system system{ cfg };

	std::array<double, 5> as;

	// Let us use an plain old for loop here because I don't see the benefit over using foreach here.
	// I do need the index here. Even if only to make the user prompt more understandable.
	for (unsigned int i = 0; i < as.size() ; i++) {
		// Prompt the user to input something
		std::cout << "Please input a" << i << ": ";
		// declare a temporary variable for the input
		string input;
		// read from cin
		std::cin >> input;
		//parse the doubles and write to the array
		as[i] = std::stod(input);
		// The obligatory newline
		std::cout << endl;
	}
	std::cout << "Thank you! I'll spawn the polynomial evaluator now!" << endl;

	scoped_actor self{ system };

	// Spawn the actor.
	// The signature of the spawn function doesn't look that straightforward,
	// I think I'll go back to spawn/3 in Erlang, thanks. :-P
	auto p = self->spawn(polynomial, as); //using type inference because I do not know the type.

	// How would I even do this with the range based for loop?
	// I would need an iterator that returns something forever.
	// That is easy, but YAGNI, so a for (;;) will do.
	for (;;) {
		std::cout << "Please input an x: ";
		// declare a temporary variable for the input
		string input;
		// read from cin
		std::cin >> input;
		// parse the x
		double x = stod(input);
		// send it to the actor
		self->send(p, atom("calc"), x);

		//receive from the actor
		self->receive(
			[&](double evaluatedPolynomial) {
			// I'd love to write unit tests for this here instead of writing it to aout.
			// Do you have something like eunit or common_test?
			aout(self) << evaluatedPolynomial << endl;
		}
		);
		// how do I make this receive synchronous?
		// I don't like using sleep here.
		std::this_thread::sleep_for(std::chrono::milliseconds(50));
	}

}
<|endoftext|>


<commit_before>/*
 *
 * Copyright (C) 2009, Joacim Jacobsson ( j dot jacobsson at gmail dot com )
 * All rights reserved.
 *
 * See LICENSE file for details
 *
 */

#include <callback/callback.h>
#include <callback/instructions.h>

namespace callback
{

    int run_program( CallbackProgram* info )
    {
        ProgramHeader*  ph   =   (ProgramHeader*)(info->m_Program);
        Instruction*    i    =   (Instruction*)((char*)(info->m_Program) + sizeof(ProgramHeader));
        char*           bss  =   (char*)info->m_bss;
        char*           data =   ((char*)(i)) + (sizeof(Instruction) * ph->m_IC);
        BssHeader*      bh   =   (BssHeader*)(bss);
        callbackHandler ch   =   info->m_callback;
        DebugHandler    dh   =   info->m_Debug;

        bool exit = false;
        while( !exit )
        {
            const Instruction& inst = i[bh->m_IP];
            ++bh->m_IP;
            ++bh->m_IC;
            switch( inst.m_I )
            {
            case INST_CALL_DEBUG_FN:
                //if( dh )
                //    dh( info, ph, bh );
                break;
            case INST_CALL_CONS_FUN:
                ch(
                    bh->m_R[inst.m_A1],
                    ACT_CONSTRUCT,
                    (void*)bh->m_R[inst.m_A2],
                    (void**)bh->m_R[inst.m_A3],
                    info->m_UserData
                );
                bh->m_R[inst.m_A1] = 0;
                bh->m_R[inst.m_A2] = 0;
                bh->m_R[inst.m_A3] = 0;
                break;
            case INST_CALL_EXEC_FUN:
                bh->m_RE = ch(
                    bh->m_R[inst.m_A1],
                    ACT_EXECUTE,
                    (void*)bh->m_R[inst.m_A2],
                    (void**)bh->m_R[inst.m_A3],
                    info->m_UserData
                );
                bh->m_R[inst.m_A1] = 0;
                bh->m_R[inst.m_A2] = 0;
                bh->m_R[inst.m_A3] = 0;
                break;
            case INST_CALL_DEST_FUN:
                ch(
                    bh->m_R[inst.m_A1],
                    ACT_DESTRUCT,
                    (void*)bh->m_R[inst.m_A2],
                    (void**)bh->m_R[inst.m_A3],
                    info->m_UserData
                );
                bh->m_R[inst.m_A1] = 0;
                bh->m_R[inst.m_A2] = 0;
                bh->m_R[inst.m_A3] = 0;
                break;

            case INST_CALL_PRUN_FUN:
                bh->m_RE = ch(
                    bh->m_R[inst.m_A1],
                    ACT_PRUNE,
                    (void*)bh->m_R[inst.m_A2],
                    (void**)bh->m_R[inst.m_A3],
                    info->m_UserData
                );
                bh->m_R[inst.m_A1] = 0;
                bh->m_R[inst.m_A2] = 0;
                bh->m_R[inst.m_A3] = 0;
                break;
            case INST_CALL_MODI_FUN:
                bh->m_RE = ch(
                    bh->m_R[inst.m_A1],
                    ACT_MODIFY,
                    (void*)bh->m_R[inst.m_A2],
                    (void**)bh->m_R[inst.m_A3],
                    info->m_UserData
                );
                bh->m_R[inst.m_A1] = 0;
                bh->m_R[inst.m_A2] = 0;
                bh->m_R[inst.m_A3] = 0;
                break;
            case INST_JABC_R_EQUA_C:
                if( bh->m_RE == inst.m_A2 )
                    bh->m_IP = inst.m_A1;
                break;
            case INST_JABC_R_DIFF_C:
                if( bh->m_RE != inst.m_A2 )
                    bh->m_IP = inst.m_A1;
                break;
            case INST_JABC_C_EQUA_B:
                if( inst.m_A2 == *((int*)&(bss[inst.m_A3])) )
                    bh->m_IP = inst.m_A1;
                break;
            case INST_JABC_C_DIFF_B:
                if( inst.m_A2 != *((int*)&(bss[inst.m_A3])) )
                    bh->m_IP = inst.m_A1;
                break;
            case INST_JABB_C_EQUA_B:
                if( inst.m_A2 == *((int*)&(bss[inst.m_A3])) )
                    bh->m_IP = *((int*)&(bss[inst.m_A1]));
                break;
            case INST_JABB_C_DIFF_B:
                if( inst.m_A2 != *((int*)&(bss[inst.m_A3])) )
                    bh->m_IP = *((int*)&(bss[inst.m_A1]));
                break;
            case INST_JABB_B_EQUA_B:
                if( *((int*)&(bss[inst.m_A2])) == *((int*)&(bss[inst.m_A3])) )
                    bh->m_IP = *((int*)&(bss[inst.m_A1]));
                break;
            case INST_JABB_B_DIFF_B:
                if( *((int*)&(bss[inst.m_A2])) != *((int*)&(bss[inst.m_A3])) )
                    bh->m_IP = *((int*)&(bss[inst.m_A1]));
                break;
            case INST_JABC_CONSTANT:
                bh->m_IP = inst.m_A1;
                break;
            case INST_JREC_CONSTANT:
                bh->m_IP += inst.m_A1;
                break;
            case INST_JABB_BSSVALUE:
                bh->m_IP = *((int*)&(bss[inst.m_A1]));
                break;
            case INST_JREB_BSSVALUE:
                bh->m_IP += *((int*)&(bss[inst.m_A1]));
                break;
            case INST_JABC_S_C_IN_B:
                bh->m_IP = inst.m_A1;
                *((int*)&(bss[inst.m_A2])) = inst.m_A3;
                break;
            case INST_JREC_S_C_IN_B:
                bh->m_IP += inst.m_A1;
                *((int*)&(bss[inst.m_A2])) = inst.m_A3;
                break;
            case INST_JABB_S_C_IN_B:
                bh->m_IP = *((int*)&(bss[inst.m_A1]));
                *((int*)&(bss[inst.m_A2])) = inst.m_A3;
                break;
            case INST_JREB_S_C_IN_B:
                bh->m_IP += *((int*)&(bss[inst.m_A1]));
                *((int*)&(bss[inst.m_A2])) = inst.m_A3;
                break;
            case INST__STORE_R_IN_B:
                *((int*)&(bss[inst.m_A1])) = bh->m_RE;
                break;
            case INST__STORE_B_IN_R:
                bh->m_RE = *((int*)&(bss[inst.m_A1]));
                break;
            case INST__STORE_C_IN_B:
                *((int*)&(bss[inst.m_A1])) = inst.m_A2;
                break;
            case INST__STORE_B_IN_B:
                *((int*)&(bss[inst.m_A1])) = *((int*)&(bss[inst.m_A2]));
                break;
            case INST__STORE_C_IN_R:
                bh->m_RE = inst.m_A1;
                break;
            case INST_STORE_PD_IN_B:
                *(int*)(&bss[inst.m_A1]) = (int)(&data[inst.m_A2]);
                break;
            case INST_STORE_PB_IN_R:
                bh->m_R[inst.m_A1] = (int)(&bss[inst.m_A2]);
                break;
            case INST__INC_BSSVALUE:
                *((int*)&(bss[inst.m_A1])) += inst.m_A2;
                break;
            case INST__DEC_BSSVALUE:
                *((int*)&(bss[inst.m_A1])) += inst.m_A2;
                break;
            case INST_LOAD_REGISTRY:
                bh->m_R[inst.m_A1] = (((int)inst.m_A2)<<16) + inst.m_A3;
                break;
            case INST_______SUSPEND:
                bh->m_IP = 0;
                exit     = true;
                break;
            }
        }
        return bh->m_RE;
    }

}
<commit_msg>Got rid of the outer "while" in the VM in favor of a goto. Yes. A goto. really.<commit_after>/*
 *
 * Copyright (C) 2009, Joacim Jacobsson ( j dot jacobsson at gmail dot com )
 * All rights reserved.
 *
 * See LICENSE file for details
 *
 */

#include <callback/callback.h>
#include <callback/instructions.h>

namespace callback
{

    int run_program( CallbackProgram* info )
    {
        ProgramHeader*  ph   =   (ProgramHeader*)(info->m_Program);
        Instruction*    i    =   (Instruction*)((char*)(info->m_Program) + sizeof(ProgramHeader));
        char*           bss  =   (char*)info->m_bss;
        char*           data =   ((char*)(i)) + (sizeof(Instruction) * ph->m_IC);
        BssHeader*      bh   =   (BssHeader*)(bss);
        callbackHandler ch   =   info->m_callback;
        DebugHandler    dh   =   info->m_Debug;

start:
		const Instruction& inst = i[bh->m_IP];
		++bh->m_IP;
		++bh->m_IC;
		switch( inst.m_I )
		{
		case INST_CALL_DEBUG_FN:
			//if( dh )
			//    dh( info, ph, bh );
			break;
		case INST_CALL_CONS_FUN:
			ch(
				bh->m_R[inst.m_A1],
				ACT_CONSTRUCT,
				(void*)bh->m_R[inst.m_A2],
				(void**)bh->m_R[inst.m_A3],
				info->m_UserData
			);
			bh->m_R[inst.m_A1] = 0;
			bh->m_R[inst.m_A2] = 0;
			bh->m_R[inst.m_A3] = 0;
			break;
		case INST_CALL_EXEC_FUN:
			bh->m_RE = ch(
				bh->m_R[inst.m_A1],
				ACT_EXECUTE,
				(void*)bh->m_R[inst.m_A2],
				(void**)bh->m_R[inst.m_A3],
				info->m_UserData
			);
			bh->m_R[inst.m_A1] = 0;
			bh->m_R[inst.m_A2] = 0;
			bh->m_R[inst.m_A3] = 0;
			break;
		case INST_CALL_DEST_FUN:
			ch(
				bh->m_R[inst.m_A1],
				ACT_DESTRUCT,
				(void*)bh->m_R[inst.m_A2],
				(void**)bh->m_R[inst.m_A3],
				info->m_UserData
			);
			bh->m_R[inst.m_A1] = 0;
			bh->m_R[inst.m_A2] = 0;
			bh->m_R[inst.m_A3] = 0;
			break;

		case INST_CALL_PRUN_FUN:
			bh->m_RE = ch(
				bh->m_R[inst.m_A1],
				ACT_PRUNE,
				(void*)bh->m_R[inst.m_A2],
				(void**)bh->m_R[inst.m_A3],
				info->m_UserData
			);
			bh->m_R[inst.m_A1] = 0;
			bh->m_R[inst.m_A2] = 0;
			bh->m_R[inst.m_A3] = 0;
			break;
		case INST_CALL_MODI_FUN:
			bh->m_RE = ch(
				bh->m_R[inst.m_A1],
				ACT_MODIFY,
				(void*)bh->m_R[inst.m_A2],
				(void**)bh->m_R[inst.m_A3],
				info->m_UserData
			);
			bh->m_R[inst.m_A1] = 0;
			bh->m_R[inst.m_A2] = 0;
			bh->m_R[inst.m_A3] = 0;
			break;
		case INST_JABC_R_EQUA_C:
			if( bh->m_RE == inst.m_A2 )
				bh->m_IP = inst.m_A1;
			break;
		case INST_JABC_R_DIFF_C:
			if( bh->m_RE != inst.m_A2 )
				bh->m_IP = inst.m_A1;
			break;
		case INST_JABC_C_EQUA_B:
			if( inst.m_A2 == *((int*)&(bss[inst.m_A3])) )
				bh->m_IP = inst.m_A1;
			break;
		case INST_JABC_C_DIFF_B:
			if( inst.m_A2 != *((int*)&(bss[inst.m_A3])) )
				bh->m_IP = inst.m_A1;
			break;
		case INST_JABB_C_EQUA_B:
			if( inst.m_A2 == *((int*)&(bss[inst.m_A3])) )
				bh->m_IP = *((int*)&(bss[inst.m_A1]));
			break;
		case INST_JABB_C_DIFF_B:
			if( inst.m_A2 != *((int*)&(bss[inst.m_A3])) )
				bh->m_IP = *((int*)&(bss[inst.m_A1]));
			break;
		case INST_JABB_B_EQUA_B:
			if( *((int*)&(bss[inst.m_A2])) == *((int*)&(bss[inst.m_A3])) )
				bh->m_IP = *((int*)&(bss[inst.m_A1]));
			break;
		case INST_JABB_B_DIFF_B:
			if( *((int*)&(bss[inst.m_A2])) != *((int*)&(bss[inst.m_A3])) )
				bh->m_IP = *((int*)&(bss[inst.m_A1]));
			break;
		case INST_JABC_CONSTANT:
			bh->m_IP = inst.m_A1;
			break;
		case INST_JREC_CONSTANT:
			bh->m_IP += inst.m_A1;
			break;
		case INST_JABB_BSSVALUE:
			bh->m_IP = *((int*)&(bss[inst.m_A1]));
			break;
		case INST_JREB_BSSVALUE:
			bh->m_IP += *((int*)&(bss[inst.m_A1]));
			break;
		case INST_JABC_S_C_IN_B:
			bh->m_IP = inst.m_A1;
			*((int*)&(bss[inst.m_A2])) = inst.m_A3;
			break;
		case INST_JREC_S_C_IN_B:
			bh->m_IP += inst.m_A1;
			*((int*)&(bss[inst.m_A2])) = inst.m_A3;
			break;
		case INST_JABB_S_C_IN_B:
			bh->m_IP = *((int*)&(bss[inst.m_A1]));
			*((int*)&(bss[inst.m_A2])) = inst.m_A3;
			break;
		case INST_JREB_S_C_IN_B:
			bh->m_IP += *((int*)&(bss[inst.m_A1]));
			*((int*)&(bss[inst.m_A2])) = inst.m_A3;
			break;
		case INST__STORE_R_IN_B:
			*((int*)&(bss[inst.m_A1])) = bh->m_RE;
			break;
		case INST__STORE_B_IN_R:
			bh->m_RE = *((int*)&(bss[inst.m_A1]));
			break;
		case INST__STORE_C_IN_B:
			*((int*)&(bss[inst.m_A1])) = inst.m_A2;
			break;
		case INST__STORE_B_IN_B:
			*((int*)&(bss[inst.m_A1])) = *((int*)&(bss[inst.m_A2]));
			break;
		case INST__STORE_C_IN_R:
			bh->m_RE = inst.m_A1;
			break;
		case INST_STORE_PD_IN_B:
			*(int*)(&bss[inst.m_A1]) = (int)(&data[inst.m_A2]);
			break;
		case INST_STORE_PB_IN_R:
			bh->m_R[inst.m_A1] = (int)(&bss[inst.m_A2]);
			break;
		case INST__INC_BSSVALUE:
			*((int*)&(bss[inst.m_A1])) += inst.m_A2;
			break;
		case INST__DEC_BSSVALUE:
			*((int*)&(bss[inst.m_A1])) += inst.m_A2;
			break;
		case INST_LOAD_REGISTRY:
			bh->m_R[inst.m_A1] = (((int)inst.m_A2)<<16) + inst.m_A3;
			break;
		case INST_______SUSPEND:
			bh->m_IP = 0;
			goto exit;
			break;
		}
		goto start;
exit:

		return bh->m_RE;
    }

}
<|endoftext|>