<commit_before>#include "linkdialog.h"

#include <QComboBox>
#include <QDialogButtonBox>
#include <QFile>
#include <QGridLayout>
#include <QLabel>
#include <QMessageBox>
#include <QSettings>
#include "common/config.h"
#include "core/application.h"
#include "core/moduleinfo.h"
#include "forms/filedialog.h"
#include "models/linksmodel.h"
#include "models/loadersmodel.h"
#include "models/prefixesmodel.h"
#include "widgets/lineedit.h"

LinkDialog::LinkDialog(QWidget* parent) :
	QDialog(parent),
	item_(nullptr)
{
	setupUi();
}

LinkItem* LinkDialog::item() const
{
	return item_;
}

void LinkDialog::setItem(LinkItem* item)
{
	item_ = item;

	if(item) {
		nameEdit_->setText(item->name());
		locationEdit_->setText(item->location());
		targetEdit_->setText(item->target());

		int index = prefixCombo_->findText(item->prefix());
		prefixCombo_->setCurrentIndex(index);

		index = loaderCombo_->findText(item->loader());
		loaderCombo_->setCurrentIndex(index);

		index = static_cast<int>(item->logLevel()) + 1;
		logLevelCombo_->setCurrentIndex(index);
	}
	else {
		nameEdit_->clear();
		locationEdit_->clear();
		targetEdit_->clear();

		int index = prefixCombo_->findText("default");
		prefixCombo_->setCurrentIndex(index);

		index = loaderCombo_->findText("default");
		loaderCombo_->setCurrentIndex(index);
	}
}

void LinkDialog::setupUi()
{
	setWindowIcon(QIcon(":/edit_link.png"));
	setWindowTitle("Link properties");
	setMinimumWidth(500);
	resize(600, 180);
	setFixedHeight(210);

	loaderCombo_ = new QComboBox;
	loaderCombo_->setModel(qApp->loaders());
	loaderCombo_->setCurrentIndex(loaderCombo_->findText("default"));

	prefixCombo_ = new QComboBox;
	prefixCombo_->setModel(qApp->prefixes());
	prefixCombo_->setCurrentIndex(prefixCombo_->findText("default"));
	connect(prefixCombo_, SIGNAL(currentIndexChanged(int)), SLOT(onPrefixChanged()));

	logLevelCombo_ = new QComboBox;
	logLevelCombo_->addItem(QIcon(":/star.png"), "default");
	logLevelCombo_->addItem(QIcon(":/mute.png"), "quiet");
	logLevelCombo_->addItem(QIcon(":/warning.png"), "error");
	logLevelCombo_->addItem(QIcon(":/trace.png"), "trace");
	logLevelCombo_->addItem(QIcon(":/bug.png"), "debug");
	logLevelCombo_->addItem(QIcon(":/scull.png"), "flood");

	targetEdit_ = new LineEdit;
	targetEdit_->setButtonEnabled(true);
	targetEdit_->setButtonStyle(LineEdit::kLightAutoRaise);
	targetEdit_->setButtonIcon(QIcon(":/open.png"));
	targetEdit_->setButtonToolTip("Browse");
	targetEdit_->setPrefix("${WINEPREFIX}/");
	targetEdit_->setPrefixColor(Qt::darkGreen);
	connect(targetEdit_, SIGNAL(buttonClicked()), SLOT(browsePlugin()));

	locationEdit_ = new LineEdit;
	locationEdit_->setButtonEnabled(true);
	locationEdit_->setButtonStyle(LineEdit::kLightAutoRaise);
	locationEdit_->setButtonIcon(QIcon(":/open.png"));
	locationEdit_->setButtonToolTip("Browse");

	QSettings settings;
	QString vstPath = settings.value("vstPath", qgetenv("VST_PATH")).toString();
	locationEdit_->setText(vstPath);
	connect(locationEdit_, SIGNAL(buttonClicked()), SLOT(browseLocation()));

	nameEdit_ = new LineEdit;

	buttons_ = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
	connect(buttons_, SIGNAL(accepted()), SLOT(accept()));
	connect(buttons_, SIGNAL(rejected()), SLOT(reject()));

	QGridLayout* mainLayout = new QGridLayout;

	mainLayout->addWidget(new QLabel("WINE loader:"), 0, 0, Qt::AlignRight);
	mainLayout->addWidget(loaderCombo_, 0, 1, 1, 1);

	mainLayout->addWidget(new QLabel("WINE prefix:"), 1, 0, Qt::AlignRight);
	mainLayout->addWidget(prefixCombo_, 1, 1, 1, 1);

	mainLayout->addWidget(new QLabel("VST plugin:"), 2, 0, Qt::AlignRight);
	mainLayout->addWidget(targetEdit_, 2, 1, 1, 2);

	mainLayout->addWidget(new QLabel("Link location:"), 3, 0, Qt::AlignRight);
	mainLayout->addWidget(locationEdit_, 3, 1, 1, 2);

	mainLayout->addWidget(new QLabel("Link name:"), 4, 0, Qt::AlignRight);
	mainLayout->addWidget(nameEdit_, 4, 1, 1, 2);

	mainLayout->addWidget(new QLabel("Log level:"), 5, 0, Qt::AlignRight);
	mainLayout->addWidget(logLevelCombo_, 5, 1, 1, 1);

	mainLayout->addWidget(new QWidget, 6, 0);

	mainLayout->addWidget(buttons_, 7, 1, 1, 2);

	mainLayout->setRowStretch(5, 1);

	mainLayout->setColumnStretch(0, 0);
	mainLayout->setColumnStretch(1, 0);
	mainLayout->setColumnStretch(2, 1);

	setLayout(mainLayout);
}

void LinkDialog::browsePlugin()
{
	QString prefix = currentPrefix();
	QFileInfo prefixInfo(prefix);

	if(!prefixInfo.isDir()) {
		QMessageBox::critical(this, "Error", "Selected prefix directory doesn't exists.");
		return;
	}

	FileDialog dialog(FileDialog::kOpenDialog);
	dialog.setAcceptMode(FileDialog::kAcceptExistingFile);
	dialog.setFilter(QDir::AllDirs | QDir::NoDotAndDotDot | QDir::Files);
	dialog.setNameFilter("*.dll");
	dialog.setWindowTitle("Select the source VST plugin");
	dialog.setRootDirectory(prefix);

	if(targetEdit_->text().isEmpty()) {
		QFileInfo info(prefixInfo.absoluteFilePath(), "drive_c");
		dialog.setDirectory(info.absoluteFilePath());
	}
	else {
		QFileInfo info(prefix, targetEdit_->text());
		while(!info.isDir())
			info = QFileInfo(info.absolutePath());

		dialog.setDirectory(info.absoluteFilePath());
	}

	if(dialog.exec()) {
		int length = prefixInfo.absoluteFilePath().length() + 1; // Take '/' into account
		targetEdit_->setText(dialog.selectedPath().mid(length));

		QString name = dialog.selectedName();
		name.chop(4); // Remove ".dll" extension
		nameEdit_->setText(name);
	}
}

void LinkDialog::browseLocation()
{
	FileDialog dialog(FileDialog::kOpenDialog);
	dialog.setAcceptMode(FileDialog::kAcceptExistingDirectory);
	dialog.setFilter(QDir::AllDirs | QDir::NoDotAndDotDot);
	dialog.setWindowTitle("Select directory where the link will be placed");

	QString text = locationEdit_->text();
	if(text.isEmpty()) {
		dialog.setDirectory(QDir::homePath());
	}
	else {
		dialog.setDirectory(text);
	}

	if(dialog.exec()) {
		locationEdit_->setText(dialog.selectedPath());
	}
}

void LinkDialog::accept()
{
	QString prefix = currentPrefix();
	QFileInfo vstInfo(prefix, targetEdit_->text());

	if(!vstInfo.isFile() || vstInfo.suffix() != "dll") {
		QMessageBox::critical(this, "Error", "VST plugin is invalid or doesn't exists.");
		return;
	}

	QFileInfo locationInfo(locationEdit_->text());

	if(!locationInfo.isDir()) {
		QMessageBox::critical(this, "Error", "Location directory doesn't exists.");
		return;
	}

	QString name = nameEdit_->text();
	if(name.isEmpty()) {
		QMessageBox::critical(this, "Error", "Link name cannot be empty.");
		return;
	}

	QString pluginPath = pluginPathFor(vstInfo.absoluteFilePath());
	if(pluginPath.isEmpty()) {
		QMessageBox::critical(this, "Error", "VST plugin is corrupted.");
		return;
	}

	int index = logLevelCombo_->currentIndex();
	Airwave::LogLevel level = static_cast<Airwave::LogLevel>(index - 1);

	if(level == Airwave::LogLevel::kFlood) {
		QString message = "WARNING!
"
				"By using the 'flood' log level, you will get an enormous count of log "
				"messages from this link, the plugin performance will be low and the "
				"audio playback may become very choppy.

"
				"Do you really want to proceed?";

		if(QMessageBox::question(this, "Question", message) == QMessageBox::No)
			return;
	}

	if(!item_) {
		item_ = qApp->links()->createLink(nameEdit_->text(), locationEdit_->text(),
				targetEdit_->text(), prefixCombo_->currentText(),
				loaderCombo_->currentText());

		if(!item_) {
			QMessageBox::critical(this, "Error", "Unable to create link.");
			return;
		}

		int value = logLevelCombo_->currentIndex() - 1;
		item_->setLogLevel(static_cast<LogLevel>(value));
	}
	else {
		if(item_->name() != name) {
			LinkItem* item = qApp->links()->root()->firstChild();

			while(item) {
				if(item->name() == name) {
					QString message = QString("Link with name '%1' is already exists.")
							.arg(name);

					QMessageBox::critical(this, "Error", message);
					return;
				}

				item = item->nextSibling();
			}
		}

		QDir dir(locationInfo.absoluteFilePath());
		dir.remove(item_->name() + ".so");

		item_->setName(nameEdit_->text());
		item_->setLocation(locationEdit_->text());
		item_->setTarget(targetEdit_->text());
		item_->setPrefix(prefixCombo_->currentText());
		item_->setLoader(loaderCombo_->currentText());

		int value = logLevelCombo_->currentIndex() - 1;
		item_->setLogLevel(static_cast<LogLevel>(value));
	}

	qApp->storage()->save();
	QFile::copy(pluginPath, locationInfo.absoluteFilePath() + '/' + name + ".so");

	QDialog::accept();
}

void LinkDialog::onPrefixChanged()
{
	targetEdit_->clear();
	nameEdit_->clear();
}

QString LinkDialog::currentPrefix() const
{
	int index = prefixCombo_->currentIndex();

	if(index != -1) {
		PrefixItem* item = qApp->prefixes()->root()->childAt(index);
		if(item)
			return item->path();
	}

	return QString();
}

QString LinkDialog::pluginPathFor(const QString& vstPath) const
{
	QString pluginPath = QString::fromStdString(qApp->storage()->binariesPath());
	pluginPath += "/" PLUGIN_BASENAME;

	ModuleInfo* moduleInfo = ModuleInfo::instance();
	ModuleInfo::Arch arch = moduleInfo->getArch(vstPath);

	if(arch == ModuleInfo::kArch32) {
		return pluginPath + "-32.so";
	}
	else if(arch == ModuleInfo::kArch64) {
		return pluginPath + "-64.so";
	}

	return QString();
}
<commit_msg>Fix the forming of the plugin relative path<commit_after>#include "linkdialog.h"

#include <QComboBox>
#include <QDialogButtonBox>
#include <QFile>
#include <QGridLayout>
#include <QLabel>
#include <QMessageBox>
#include <QSettings>
#include "common/config.h"
#include "core/application.h"
#include "core/moduleinfo.h"
#include "forms/filedialog.h"
#include "models/linksmodel.h"
#include "models/loadersmodel.h"
#include "models/prefixesmodel.h"
#include "widgets/lineedit.h"

LinkDialog::LinkDialog(QWidget* parent) :
	QDialog(parent),
	item_(nullptr)
{
	setupUi();
}

LinkItem* LinkDialog::item() const
{
	return item_;
}

void LinkDialog::setItem(LinkItem* item)
{
	item_ = item;

	if(item) {
		nameEdit_->setText(item->name());
		locationEdit_->setText(item->location());
		targetEdit_->setText(item->target());

		int index = prefixCombo_->findText(item->prefix());
		prefixCombo_->setCurrentIndex(index);

		index = loaderCombo_->findText(item->loader());
		loaderCombo_->setCurrentIndex(index);

		index = static_cast<int>(item->logLevel()) + 1;
		logLevelCombo_->setCurrentIndex(index);
	}
	else {
		nameEdit_->clear();
		locationEdit_->clear();
		targetEdit_->clear();

		int index = prefixCombo_->findText("default");
		prefixCombo_->setCurrentIndex(index);

		index = loaderCombo_->findText("default");
		loaderCombo_->setCurrentIndex(index);
	}
}

void LinkDialog::setupUi()
{
	setWindowIcon(QIcon(":/edit_link.png"));
	setWindowTitle("Link properties");
	setMinimumWidth(500);
	resize(600, 180);
	setFixedHeight(210);

	loaderCombo_ = new QComboBox;
	loaderCombo_->setModel(qApp->loaders());
	loaderCombo_->setCurrentIndex(loaderCombo_->findText("default"));

	prefixCombo_ = new QComboBox;
	prefixCombo_->setModel(qApp->prefixes());
	prefixCombo_->setCurrentIndex(prefixCombo_->findText("default"));
	connect(prefixCombo_, SIGNAL(currentIndexChanged(int)), SLOT(onPrefixChanged()));

	logLevelCombo_ = new QComboBox;
	logLevelCombo_->addItem(QIcon(":/star.png"), "default");
	logLevelCombo_->addItem(QIcon(":/mute.png"), "quiet");
	logLevelCombo_->addItem(QIcon(":/warning.png"), "error");
	logLevelCombo_->addItem(QIcon(":/trace.png"), "trace");
	logLevelCombo_->addItem(QIcon(":/bug.png"), "debug");
	logLevelCombo_->addItem(QIcon(":/scull.png"), "flood");

	targetEdit_ = new LineEdit;
	targetEdit_->setButtonEnabled(true);
	targetEdit_->setButtonStyle(LineEdit::kLightAutoRaise);
	targetEdit_->setButtonIcon(QIcon(":/open.png"));
	targetEdit_->setButtonToolTip("Browse");
	targetEdit_->setPrefix("${WINEPREFIX}/");
	targetEdit_->setPrefixColor(Qt::darkGreen);
	connect(targetEdit_, SIGNAL(buttonClicked()), SLOT(browsePlugin()));

	locationEdit_ = new LineEdit;
	locationEdit_->setButtonEnabled(true);
	locationEdit_->setButtonStyle(LineEdit::kLightAutoRaise);
	locationEdit_->setButtonIcon(QIcon(":/open.png"));
	locationEdit_->setButtonToolTip("Browse");

	QSettings settings;
	QString vstPath = settings.value("vstPath", qgetenv("VST_PATH")).toString();
	locationEdit_->setText(vstPath);
	connect(locationEdit_, SIGNAL(buttonClicked()), SLOT(browseLocation()));

	nameEdit_ = new LineEdit;

	buttons_ = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
	connect(buttons_, SIGNAL(accepted()), SLOT(accept()));
	connect(buttons_, SIGNAL(rejected()), SLOT(reject()));

	QGridLayout* mainLayout = new QGridLayout;

	mainLayout->addWidget(new QLabel("WINE loader:"), 0, 0, Qt::AlignRight);
	mainLayout->addWidget(loaderCombo_, 0, 1, 1, 1);

	mainLayout->addWidget(new QLabel("WINE prefix:"), 1, 0, Qt::AlignRight);
	mainLayout->addWidget(prefixCombo_, 1, 1, 1, 1);

	mainLayout->addWidget(new QLabel("VST plugin:"), 2, 0, Qt::AlignRight);
	mainLayout->addWidget(targetEdit_, 2, 1, 1, 2);

	mainLayout->addWidget(new QLabel("Link location:"), 3, 0, Qt::AlignRight);
	mainLayout->addWidget(locationEdit_, 3, 1, 1, 2);

	mainLayout->addWidget(new QLabel("Link name:"), 4, 0, Qt::AlignRight);
	mainLayout->addWidget(nameEdit_, 4, 1, 1, 2);

	mainLayout->addWidget(new QLabel("Log level:"), 5, 0, Qt::AlignRight);
	mainLayout->addWidget(logLevelCombo_, 5, 1, 1, 1);

	mainLayout->addWidget(new QWidget, 6, 0);

	mainLayout->addWidget(buttons_, 7, 1, 1, 2);

	mainLayout->setRowStretch(5, 1);

	mainLayout->setColumnStretch(0, 0);
	mainLayout->setColumnStretch(1, 0);
	mainLayout->setColumnStretch(2, 1);

	setLayout(mainLayout);
}

void LinkDialog::browsePlugin()
{
	QString prefix = currentPrefix();
	QFileInfo prefixInfo(prefix);

	if(!prefixInfo.isDir()) {
		QMessageBox::critical(this, "Error", "Selected prefix directory doesn't exists.");
		return;
	}

	FileDialog dialog(FileDialog::kOpenDialog);
	dialog.setAcceptMode(FileDialog::kAcceptExistingFile);
	dialog.setFilter(QDir::AllDirs | QDir::NoDotAndDotDot | QDir::Files);
	dialog.setNameFilter("*.dll");
	dialog.setWindowTitle("Select the source VST plugin");
	dialog.setRootDirectory(prefix);

	if(targetEdit_->text().isEmpty()) {
		QFileInfo info(prefixInfo.absoluteFilePath(), "drive_c");
		dialog.setDirectory(info.absoluteFilePath());
	}
	else {
		QFileInfo info(prefix, targetEdit_->text());
		while(!info.isDir())
			info = QFileInfo(info.absolutePath());

		dialog.setDirectory(info.absoluteFilePath());
	}

	if(dialog.exec()) {
		QString prefixPath = prefixInfo.absoluteFilePath();
		int length = prefixPath.length();
		if(!prefixPath.endsWith('/'))
			length++;

		targetEdit_->setText(dialog.selectedPath().mid(length));

		QString name = dialog.selectedName();
		name.chop(4); // Remove ".dll" extension
		nameEdit_->setText(name);
	}
}

void LinkDialog::browseLocation()
{
	FileDialog dialog(FileDialog::kOpenDialog);
	dialog.setAcceptMode(FileDialog::kAcceptExistingDirectory);
	dialog.setFilter(QDir::AllDirs | QDir::NoDotAndDotDot);
	dialog.setWindowTitle("Select directory where the link will be placed");

	QString text = locationEdit_->text();
	if(text.isEmpty()) {
		dialog.setDirectory(QDir::homePath());
	}
	else {
		dialog.setDirectory(text);
	}

	if(dialog.exec()) {
		locationEdit_->setText(dialog.selectedPath());
	}
}

void LinkDialog::accept()
{
	QString prefix = currentPrefix();
	QFileInfo vstInfo(prefix, targetEdit_->text());

	if(!vstInfo.isFile() || vstInfo.suffix() != "dll") {
		QMessageBox::critical(this, "Error", "VST plugin is invalid or doesn't exists.");
		return;
	}

	QFileInfo locationInfo(locationEdit_->text());

	if(!locationInfo.isDir()) {
		QMessageBox::critical(this, "Error", "Location directory doesn't exists.");
		return;
	}

	QString name = nameEdit_->text();
	if(name.isEmpty()) {
		QMessageBox::critical(this, "Error", "Link name cannot be empty.");
		return;
	}

	QString pluginPath = pluginPathFor(vstInfo.absoluteFilePath());
	if(pluginPath.isEmpty()) {
		QMessageBox::critical(this, "Error", "VST plugin is corrupted.");
		return;
	}

	int index = logLevelCombo_->currentIndex();
	Airwave::LogLevel level = static_cast<Airwave::LogLevel>(index - 1);

	if(level == Airwave::LogLevel::kFlood) {
		QString message = "WARNING!
"
				"By using the 'flood' log level, you will get an enormous count of log "
				"messages from this link, the plugin performance will be low and the "
				"audio playback may become very choppy.

"
				"Do you really want to proceed?";

		if(QMessageBox::question(this, "Question", message) == QMessageBox::No)
			return;
	}

	if(!item_) {
		item_ = qApp->links()->createLink(nameEdit_->text(), locationEdit_->text(),
				targetEdit_->text(), prefixCombo_->currentText(),
				loaderCombo_->currentText());

		if(!item_) {
			QMessageBox::critical(this, "Error", "Unable to create link.");
			return;
		}

		int value = logLevelCombo_->currentIndex() - 1;
		item_->setLogLevel(static_cast<LogLevel>(value));
	}
	else {
		if(item_->name() != name) {
			LinkItem* item = qApp->links()->root()->firstChild();

			while(item) {
				if(item->name() == name) {
					QString message = QString("Link with name '%1' is already exists.")
							.arg(name);

					QMessageBox::critical(this, "Error", message);
					return;
				}

				item = item->nextSibling();
			}
		}

		QDir dir(locationInfo.absoluteFilePath());
		dir.remove(item_->name() + ".so");

		item_->setName(nameEdit_->text());
		item_->setLocation(locationEdit_->text());
		item_->setTarget(targetEdit_->text());
		item_->setPrefix(prefixCombo_->currentText());
		item_->setLoader(loaderCombo_->currentText());

		int value = logLevelCombo_->currentIndex() - 1;
		item_->setLogLevel(static_cast<LogLevel>(value));
	}

	qApp->storage()->save();
	QFile::copy(pluginPath, locationInfo.absoluteFilePath() + '/' + name + ".so");

	QDialog::accept();
}

void LinkDialog::onPrefixChanged()
{
	targetEdit_->clear();
	nameEdit_->clear();
}

QString LinkDialog::currentPrefix() const
{
	int index = prefixCombo_->currentIndex();

	if(index != -1) {
		PrefixItem* item = qApp->prefixes()->root()->childAt(index);
		if(item)
			return item->path();
	}

	return QString();
}

QString LinkDialog::pluginPathFor(const QString& vstPath) const
{
	QString pluginPath = QString::fromStdString(qApp->storage()->binariesPath());
	pluginPath += "/" PLUGIN_BASENAME;

	ModuleInfo* moduleInfo = ModuleInfo::instance();
	ModuleInfo::Arch arch = moduleInfo->getArch(vstPath);

	if(arch == ModuleInfo::kArch32) {
		return pluginPath + "-32.so";
	}
	else if(arch == ModuleInfo::kArch64) {
		return pluginPath + "-64.so";
	}

	return QString();
}
<|endoftext|>


<commit_before>/**
 * @file max_ip_test.cpp
 * @author Ryan Curtin
 *
 * Ensure that the maximum inner product search is successful.
 */
#include <mlpack/core.hpp>
#include <mlpack/methods/maxip/max_ip.hpp>
#include <mlpack/core/kernels/linear_kernel.hpp>

#include <boost/test/unit_test.hpp>
#include "old_boost_test_definitions.hpp"

using namespace mlpack;
using namespace mlpack::tree;
using namespace mlpack::maxip;
using namespace mlpack::kernel;

BOOST_AUTO_TEST_SUITE(MaxIPTest);

/**
 * Compare single-tree and naive.
 */
BOOST_AUTO_TEST_CASE(SingleTreeVsNaive)
{
  // First create a random dataset.
  arma::mat data;
  srand(time(NULL));
  data.randn(5, 1000);

  // Now run MaxIP naively.
  MaxIP<LinearKernel> naive(data, false, true);

  arma::Mat<size_t> naiveIndices;
  arma::mat naiveProducts;
  naive.Search(10, naiveIndices, naiveProducts);

  // Now run it in single-tree mode.
  MaxIP<LinearKernel> single(data, true);

  arma::Mat<size_t> singleIndices;
  arma::mat singleProducts;
  single.Search(10, singleIndices, singleProducts);

  // Compare the results.
  for (size_t q = 0; q < singleIndices.n_cols; ++q)
  {
    for (size_t r = 0; r < singleIndices.n_rows; ++r)
    {
      BOOST_REQUIRE_EQUAL(singleIndices(r, q), naiveIndices(r, q));
      BOOST_REQUIRE_CLOSE(singleProducts(r, q), naiveProducts(r, q), 1e-5);
    }
  }
}

BOOST_AUTO_TEST_SUITE_END();
<commit_msg>Put ugly global variable in so it compiles.  This will be cleaned later...<commit_after>/**
 * @file max_ip_test.cpp
 * @author Ryan Curtin
 *
 * Ensure that the maximum inner product search is successful.
 */
#include <stddef.h>
size_t distanceEvaluations;

#include <mlpack/core.hpp>
#include <mlpack/methods/maxip/max_ip.hpp>
#include <mlpack/core/kernels/linear_kernel.hpp>

#include <boost/test/unit_test.hpp>
#include "old_boost_test_definitions.hpp"

using namespace mlpack;
using namespace mlpack::tree;
using namespace mlpack::maxip;
using namespace mlpack::kernel;

BOOST_AUTO_TEST_SUITE(MaxIPTest);

/**
 * Compare single-tree and naive.
 */
BOOST_AUTO_TEST_CASE(SingleTreeVsNaive)
{
  distanceEvaluations = 0;

  // First create a random dataset.
  arma::mat data;
  srand(time(NULL));
  data.randn(5, 1000);

  // Now run MaxIP naively.
  MaxIP<LinearKernel> naive(data, false, true);

  arma::Mat<size_t> naiveIndices;
  arma::mat naiveProducts;
  naive.Search(10, naiveIndices, naiveProducts);

  // Now run it in single-tree mode.
  MaxIP<LinearKernel> single(data, true);

  arma::Mat<size_t> singleIndices;
  arma::mat singleProducts;
  single.Search(10, singleIndices, singleProducts);

  // Compare the results.
  for (size_t q = 0; q < singleIndices.n_cols; ++q)
  {
    for (size_t r = 0; r < singleIndices.n_rows; ++r)
    {
      BOOST_REQUIRE_EQUAL(singleIndices(r, q), naiveIndices(r, q));
      BOOST_REQUIRE_CLOSE(singleProducts(r, q), naiveProducts(r, q), 1e-5);
    }
  }
}

BOOST_AUTO_TEST_SUITE_END();
<|endoftext|>


<commit_before>// __BEGIN_LICENSE__
//  Copyright (c) 2009-2013, United States Government as represented by the
//  Administrator of the National Aeronautics and Space Administration. All
//  rights reserved.
//
//  The NGT platform is licensed under the Apache License, Version 2.0 (the
//  "License"); you may not use this file except in compliance with the
//  License. You may obtain a copy of the License at
//  http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
// __END_LICENSE__

// Given a set of xyz points, create an xy grid. For every node in the
// grid, combine all points within given radius of the grid point and
// calculate a single z value at the grid point.

#include <vw/Core/Exception.h>
#include <vw/Core/FundamentalTypes.h>
#include <asp/Core/Point2Grid.h>
#include <vw/Math/Functors.h>

#include <iostream>

using namespace std;
using namespace vw;

namespace asp {

// ===========================================================================
// Class Member Functions
// ===========================================================================

Point2Grid::Point2Grid(int width, int height,
                       ImageView<double> & buffer, ImageView<double> & weights,
                       double x0, double y0, double grid_size, double min_spacing,
                       double radius, double sigma_factor,
                       FilterType filter, double percentile):
  m_width(width), m_height(height),
  m_buffer(buffer), m_weights(weights),
  m_x0(x0), m_y0(y0), m_grid_size(grid_size),
  m_radius(radius), m_filter(filter), m_percentile(percentile){

  if (m_grid_size <= 0)
    vw_throw( ArgumentErr() << "Point2Grid: Grid size must be > 0.\n" );
  if (m_radius <= 0)
    vw_throw( ArgumentErr() << "Point2Grid: Search radius must be > 0.\n" );

  if (m_filter == f_percentile && (m_percentile < 0 || m_percentile > 100.0) )
    vw_throw( ArgumentErr() << "Point2Grid: Expecting the percentile in the range 0.0 to 100.0.\n" );

  // Stop here if we don't need to create gaussian weights
  if (m_filter != f_weighted_average)
    return;

  // By the time we reached the distance 'spacing' from the origin, we
  // want the Gaussian exp(-sigma*x^2) to decay to given value.  Note
  // that the user may choose to make the grid size very small, but we
  // put a limit to how small 'spacing' gets, that is, how large sigma
  // gets, to ensure that the DEM stays smooth.
  double spacing = std::max(grid_size, min_spacing);
  double val = 0.25;
  double sigma = -log(val)/spacing/spacing;

  // Override this if passed from outside
  if (sigma_factor > 0)
    sigma = sigma_factor/spacing/spacing;

  // Sample the gaussian for speed
  int num_samples = 1000;
  m_dx = m_radius/(num_samples - 1.0);
  m_sampled_gauss.resize(num_samples);
  for (int k = 0; k < num_samples; k++){
    double dist = k*m_dx;
    m_sampled_gauss[k] = exp(-sigma*dist*dist);
  }

}

void Point2Grid::Clear(const float value) {
  m_buffer.set_size (m_width, m_height);
  m_weights.set_size (m_width, m_height);
  for (int c = 0; c < m_buffer.cols(); c++){
    for (int r = 0; r < m_buffer.rows(); r++){
      m_buffer (c, r) = value; // usually this is the no-data value
      m_weights(c, r) = 0.0;
    }
  }

  // For these we need to keep all values (in fact, for stddev we could get away with less,
  // but it is not worth trying so hard).
  if (m_filter == f_median || m_filter == f_stddev ||
      m_filter == f_nmad || m_filter == f_percentile) {
    m_vals.set_size(m_width, m_height);
  }

}

void Point2Grid::AddPoint(double x, double y, double z){

  int minx = std::max( (int)ceil( (x - m_radius - m_x0)/m_grid_size ), 0 );
  int miny = std::max( (int)ceil( (y - m_radius - m_y0)/m_grid_size ), 0 );

  int maxx = std::min( (int)floor( (x + m_radius - m_x0)/m_grid_size ), m_buffer.cols() - 1 );
  int maxy = std::min( (int)floor( (y + m_radius - m_y0)/m_grid_size ), m_buffer.rows() - 1 );

  // Add the contribution of current point to all grid points within radius
  for (int ix = minx; ix <= maxx; ix++){
    for (int iy = miny; iy <= maxy; iy++){

      double gx = m_x0 + ix*m_grid_size;
      double gy = m_y0 + iy*m_grid_size;
      double dist = sqrt( (x-gx)*(x-gx) + (y-gy)*(y-gy) );
      if ( dist > m_radius ) continue;

      if (m_filter == f_weighted_average) {
        double wt = m_sampled_gauss[(int)round(dist/m_dx)];
        if (wt <= 0) continue;
        if (m_weights(ix, iy) == 0) m_buffer(ix, iy) = 0.0; // set to 0 before incrementing below
        m_buffer(ix, iy)  += z*wt;
        m_weights(ix, iy) += wt;

      }else if (m_filter == f_mean){
        if (m_weights(ix, iy) == 0) m_buffer(ix, iy) = 0.0; // set to 0 before incrementing below
        m_buffer(ix, iy)  += z;
        m_weights(ix, iy) += 1;

      }else if (m_filter == f_min){
        if (m_weights(ix, iy) == 0) {
          m_buffer(ix, iy)  = z; // first time we set the value
          m_weights(ix, iy) = 1; // mark the fact that the buffer was initialized
        }else
          m_buffer(ix, iy) = std::min(m_buffer(ix, iy), z);

      }else if (m_filter == f_max){
        if (m_weights(ix, iy) == 0) {
          m_buffer(ix, iy)  = z; // first time we set the value
          m_weights(ix, iy) = 1; // mark the fact that the buffer was initialized
        }else
          m_buffer(ix, iy) = std::max(m_buffer(ix, iy), z);

      }else if (m_filter == f_count){
        if (m_weights(ix, iy) == 0) {
          m_weights(ix, iy) = 1; // mark the fact that the buffer was initialized
        }else
          m_weights(ix, iy) += 1;

      }else if (m_filter == f_stddev || m_filter == f_median ||
                m_filter == f_nmad   || m_filter == f_percentile){
        m_vals(ix, iy).push_back(z); // not strictly needed for stddev
      }

    }

  }
}

void Point2Grid::normalize(){
  for (int c = 0; c < m_buffer.cols(); c++){
    for (int r = 0; r < m_buffer.rows(); r++){

      if (m_filter == f_weighted_average || m_filter == f_mean) {
        if (m_weights(c, r) > 0)
          m_buffer (c, r) /= m_weights(c, r);

      }else if (m_filter == f_count)
        m_buffer(c, r) = m_weights(c, r); // hence instead of no-data we will have always 0

      else if (m_filter == f_stddev){
        if (m_vals(c, r).empty())
          continue; // nothing to compute
        vw::math::StdDevAccumulator<double> V;
        for (size_t it = 0; it < m_vals(c, r).size(); it++)
          V(m_vals(c, r)[it]);
        m_buffer(c, r) = V.value(); // test with mean!!!
      }

      else if (m_filter == f_median){
        if (m_vals(c, r).empty())
          continue; // nothing to compute
        vw::math::MedianAccumulator<double> V;
        for (size_t it = 0; it < m_vals(c, r).size(); it++)
          V(m_vals(c, r)[it]);
        m_buffer(c, r) = V.value(); // test with destructive mean!!!
      }

      else if (m_filter == f_nmad){
        if (m_vals(c, r).empty())
          continue; // nothing to compute
        m_buffer(c, r) = vw::math::destructive_nmad(m_vals(c, r)); // test with destructive mean!!!
      }

      else if (m_filter == f_percentile){
        if (m_vals(c, r).empty())
          continue; // nothing to compute
        m_buffer(c, r) = vw::math::destructive_percentile(m_vals(c, r), m_percentile); // compare with median!
      }

    }
  }
}

} // end namespace asp
<commit_msg>Minor comment cleanup<commit_after>// __BEGIN_LICENSE__
//  Copyright (c) 2009-2013, United States Government as represented by the
//  Administrator of the National Aeronautics and Space Administration. All
//  rights reserved.
//
//  The NGT platform is licensed under the Apache License, Version 2.0 (the
//  "License"); you may not use this file except in compliance with the
//  License. You may obtain a copy of the License at
//  http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
// __END_LICENSE__

// Given a set of xyz points, create an xy grid. For every node in the
// grid, combine all points within given radius of the grid point and
// calculate a single z value at the grid point.

#include <vw/Core/Exception.h>
#include <vw/Core/FundamentalTypes.h>
#include <asp/Core/Point2Grid.h>
#include <vw/Math/Functors.h>

#include <iostream>

using namespace std;
using namespace vw;

namespace asp {

// ===========================================================================
// Class Member Functions
// ===========================================================================

Point2Grid::Point2Grid(int width, int height,
                       ImageView<double> & buffer, ImageView<double> & weights,
                       double x0, double y0, double grid_size, double min_spacing,
                       double radius, double sigma_factor,
                       FilterType filter, double percentile):
  m_width(width), m_height(height),
  m_buffer(buffer), m_weights(weights),
  m_x0(x0), m_y0(y0), m_grid_size(grid_size),
  m_radius(radius), m_filter(filter), m_percentile(percentile){

  if (m_grid_size <= 0)
    vw_throw( ArgumentErr() << "Point2Grid: Grid size must be > 0.\n" );
  if (m_radius <= 0)
    vw_throw( ArgumentErr() << "Point2Grid: Search radius must be > 0.\n" );

  if (m_filter == f_percentile && (m_percentile < 0 || m_percentile > 100.0) )
    vw_throw( ArgumentErr() << "Point2Grid: Expecting the percentile in the range 0.0 to 100.0.\n" );

  // Stop here if we don't need to create gaussian weights
  if (m_filter != f_weighted_average)
    return;

  // By the time we reached the distance 'spacing' from the origin, we
  // want the Gaussian exp(-sigma*x^2) to decay to given value.  Note
  // that the user may choose to make the grid size very small, but we
  // put a limit to how small 'spacing' gets, that is, how large sigma
  // gets, to ensure that the DEM stays smooth.
  double spacing = std::max(grid_size, min_spacing);
  double val = 0.25;
  double sigma = -log(val)/spacing/spacing;

  // Override this if passed from outside
  if (sigma_factor > 0)
    sigma = sigma_factor/spacing/spacing;

  // Sample the gaussian for speed
  int num_samples = 1000;
  m_dx = m_radius/(num_samples - 1.0);
  m_sampled_gauss.resize(num_samples);
  for (int k = 0; k < num_samples; k++){
    double dist = k*m_dx;
    m_sampled_gauss[k] = exp(-sigma*dist*dist);
  }

}

void Point2Grid::Clear(const float value) {
  m_buffer.set_size (m_width, m_height);
  m_weights.set_size (m_width, m_height);
  for (int c = 0; c < m_buffer.cols(); c++){
    for (int r = 0; r < m_buffer.rows(); r++){
      m_buffer (c, r) = value; // usually this is the no-data value
      m_weights(c, r) = 0.0;
    }
  }

  // For these we need to keep all values (in fact, for stddev we could get away with less,
  // but it is not worth trying so hard).
  if (m_filter == f_median || m_filter == f_stddev ||
      m_filter == f_nmad || m_filter == f_percentile) {
    m_vals.set_size(m_width, m_height);
  }

}

void Point2Grid::AddPoint(double x, double y, double z){

  int minx = std::max( (int)ceil( (x - m_radius - m_x0)/m_grid_size ), 0 );
  int miny = std::max( (int)ceil( (y - m_radius - m_y0)/m_grid_size ), 0 );

  int maxx = std::min( (int)floor( (x + m_radius - m_x0)/m_grid_size ), m_buffer.cols() - 1 );
  int maxy = std::min( (int)floor( (y + m_radius - m_y0)/m_grid_size ), m_buffer.rows() - 1 );

  // Add the contribution of current point to all grid points within radius
  for (int ix = minx; ix <= maxx; ix++){
    for (int iy = miny; iy <= maxy; iy++){

      double gx = m_x0 + ix*m_grid_size;
      double gy = m_y0 + iy*m_grid_size;
      double dist = sqrt( (x-gx)*(x-gx) + (y-gy)*(y-gy) );
      if ( dist > m_radius ) continue;

      if (m_filter == f_weighted_average) {
        double wt = m_sampled_gauss[(int)round(dist/m_dx)];
        if (wt <= 0) continue;
        if (m_weights(ix, iy) == 0) m_buffer(ix, iy) = 0.0; // set to 0 before incrementing below
        m_buffer(ix, iy)  += z*wt;
        m_weights(ix, iy) += wt;

      }else if (m_filter == f_mean){
        if (m_weights(ix, iy) == 0) m_buffer(ix, iy) = 0.0; // set to 0 before incrementing below
        m_buffer(ix, iy)  += z;
        m_weights(ix, iy) += 1;

      }else if (m_filter == f_min){
        if (m_weights(ix, iy) == 0) {
          m_buffer(ix, iy)  = z; // first time we set the value
          m_weights(ix, iy) = 1; // mark the fact that the buffer was initialized
        }else
          m_buffer(ix, iy) = std::min(m_buffer(ix, iy), z);

      }else if (m_filter == f_max){
        if (m_weights(ix, iy) == 0) {
          m_buffer(ix, iy)  = z; // first time we set the value
          m_weights(ix, iy) = 1; // mark the fact that the buffer was initialized
        }else
          m_buffer(ix, iy) = std::max(m_buffer(ix, iy), z);

      }else if (m_filter == f_count){
        if (m_weights(ix, iy) == 0) {
          m_weights(ix, iy) = 1; // mark the fact that the buffer was initialized
        }else
          m_weights(ix, iy) += 1;

      }else if (m_filter == f_stddev || m_filter == f_median ||
                m_filter == f_nmad   || m_filter == f_percentile){
        m_vals(ix, iy).push_back(z); // not strictly needed for stddev
      }

    }

  }
}

void Point2Grid::normalize(){
  for (int c = 0; c < m_buffer.cols(); c++){
    for (int r = 0; r < m_buffer.rows(); r++){

      if (m_filter == f_weighted_average || m_filter == f_mean) {
        if (m_weights(c, r) > 0)
          m_buffer (c, r) /= m_weights(c, r);

      }else if (m_filter == f_count)
        m_buffer(c, r) = m_weights(c, r); // hence instead of no-data we will have always 0

      else if (m_filter == f_stddev){
        if (m_vals(c, r).empty())
          continue; // nothing to compute
        vw::math::StdDevAccumulator<double> V;
        for (size_t it = 0; it < m_vals(c, r).size(); it++)
          V(m_vals(c, r)[it]);
        m_buffer(c, r) = V.value();
      }

      else if (m_filter == f_median){
        if (m_vals(c, r).empty())
          continue; // nothing to compute
        vw::math::MedianAccumulator<double> V;
        for (size_t it = 0; it < m_vals(c, r).size(); it++)
          V(m_vals(c, r)[it]);
        m_buffer(c, r) = V.value();
      }

      else if (m_filter == f_nmad){
        if (m_vals(c, r).empty())
          continue; // nothing to compute
        m_buffer(c, r) = vw::math::destructive_nmad(m_vals(c, r));
      }

      else if (m_filter == f_percentile){
        if (m_vals(c, r).empty())
          continue; // nothing to compute
        m_buffer(c, r) = vw::math::destructive_percentile(m_vals(c, r), m_percentile);
      }

    }
  }
}

} // end namespace asp
<|endoftext|>


<commit_before>#include <ctime>
#include <limits>
#include <fstream>
#include <iostream>
#include "vcfio.h"
#include "strsplit.h"
#include "util.h"

namespace {

const int NA = std::numeric_limits<int>::min();

// ret < 0: error; ret > 0 : ploidy
int parse_gt(const Token &t, int &a, int &b)
{
    string gt(t.data(), std::find(t.data(), t.data() + t.size(), ':'));

    if ( gt.empty() )
        return -1;

    if (gt == ".")
        return 1;

    if (gt == "./." || gt == ".|.")
        return 2;

    if (std::count(gt.begin(), gt.end(), '/') + std::count(gt.begin(), gt.end(), '|') > 1) {
        std::cerr << "ERROR: unsuppored polyploidy genotype: " << gt << "\n";
        return -1;
    }

    auto pos = gt.find_first_of("/|");
    if (pos == 0 || pos == gt.size() - 1)
        return -1;

    bool ok = false;

    if (pos == string::npos) {
        a = number<int>(gt, &ok);
        if ( ! ok || a < 0 )
            return -1;
        return 1;
    }

    auto sa = gt.substr(0,pos);
    if (sa != ".") {
        a = number<int>(sa, &ok);
        if ( ! ok || a < 0 )
            return -1;
    }

    auto sb = gt.substr(pos+1);
    if (sb != ".") {
        b = number<int>(sb, &ok);
        if ( ! ok || a < 0 )
            return -1;
    }

    return 2;
}

string datetime_now()
{
    char buf[16];
    auto t = std::time(nullptr);
    std::strftime(buf, sizeof(buf), "%Y%m%d%H%M%S", std::localtime(&t));
    return string(buf);
}

} // namespace

int read_vcf(const string &filename, Genotype &gt)
{
    std::ifstream ifs(filename);
    if ( ! ifs ) {
        std::cerr << "ERROR: can't open file for reading: " << filename << "\n";
        return 1;
    }

    auto delim = [](char c) { return c == ' ' || c == '\t' || c == '\r'; };

    size_t ln = 0;
    string ver;

    for (string line; std::getline(ifs,line); ) {
        ++ln;

        if (ln == 1 && line.compare(0,13,"##fileformat=") == 0) {
            ver = line.substr(13);
            if (ver != "VCFv4.0" && ver != "VCFv4.1" && ver != "VCFv4.2") {
                std::cerr << "ERROR: unsupported VCF format version: " << ver << "\n";
                return 1;
            }
        }

        if (line.compare(0,7,"##INFO=") == 0)
            continue;

        if (line.compare(0,9,"##FILTER=") == 0)
            continue;

        if (line.compare(0,9,"##FORMAT=") == 0)
            continue;

        if (line.compare(0,9,"##contig=") == 0)
            continue;

        if (line.compare(0,2,"##") == 0)
            continue;

        if (line.compare(0,1,"#") == 0) {
            vector<string> vs;
            strsplit(delim, line.begin(), line.end(), vs);

            if (vs.size() != 8 && vs.size() < 10) {
                std::cerr << "ERROR: incorrect number of columns in header line: " << vs.size() << "\n";
                return 1;
            }

            if (vs[0] != "#CHROM" || vs[1] != "POS" || vs[2] != "ID" || vs[3] != "REF" ||
                vs[4] != "ALT" || vs[5] != "QUAL" || vs[6] != "FILTER" || vs[7] != "INFO") {
                std::cerr << "ERROR: incorrect column names in header line: "
                          << vs[0] << "\t" << vs[1] << "\t" << vs[2] << "\t" << vs[3] << "\t"
                          << vs[4] << "\t" << vs[5] << "\t" << vs[6] << "\t" << vs[7] << "\n";
                return 1;
            }

            if (vs.size() > 9) {
                if (vs[8] != "FORMAT") {
                    std::cerr << "ERROR: FORMAT is required at 9th field in header line: " << vs[8] << "\n";
                    return 1;
                }
                gt.ind.assign(vs.begin() + 9, vs.end());
            }

            break;
        }

        std::cerr << "ERROR: #CHROME header line is required\n";
        return 1;
    }

    if ( ver.empty() ) {
        std::cerr << "ERROR: ##fileformat field is required and must be the first line\n";
        return 1;
    }

    int ploidy = -1;
    size_t ncols = gt.ind.empty() ? 8 : gt.ind.size() + 9;

    for (string line; std::getline(ifs,line); ) {
        ++ln;

        vector<Token> vt;
        strsplit(delim, line.begin(), line.end(), vt);

        if (vt.size() != ncols) {
            std::cerr << "ERROR: column count doesn't match at line " << ln << " (" << vt.size() << " != "
                      << ncols << "): " << filename << "\n";
            return 1;
        }

        gt.chr.push_back(string(vt[0]));
        gt.pos.push_back(number<int>(string(vt[1])));

        if (vt[2] == Token(".",1))
            gt.loc.push_back(string(vt[0]) + "_" + string(vt[1]));
        else
            gt.loc.push_back(string(vt[2]));

        if ( gt.ind.empty() )
            continue;

        auto format = string(vt[8]);
        if (format.compare(0,2,"GT") != 0) {
            std::cerr << "ERROR: GT is required and must be the first sub-field of FORMAT: " << format << "\n";
            return 1;
        }

        auto ref = string(vt[3]);
        auto alt = string(vt[4]);
        std::transform(ref.begin(), ref.end(), ref.begin(), ::toupper);
        std::transform(alt.begin(), alt.end(), alt.begin(), ::toupper);

        vector<string> as;
        as.push_back(ref);
        strsplit([](char c) { return c == ','; }, alt.begin(), alt.end(), as);
        gt.allele.push_back(as);
        int nas = as.size();

        vector<allele_t> v;
        for (size_t i = 9; i < ncols; ++i) {
            int a = NA, b = NA;
            int info = parse_gt(vt[i], a, b);
            if (info < 0 || a >= nas || b >= nas) {
                std::cerr << "ERROR: invalid genotype data: " << string(vt[i]) << "\n";
                return 1;
            }

            if (ploidy == -1)
                ploidy = info;

            if (info != ploidy) {
                std::cerr << "ERROR: inconsistent ploidy (" << ploidy << ") genotype: " << string(vt[i]) << "\n";
                return 1;
            }

            v.push_back(a == NA ? 0 : a + 1);
            if (ploidy == 2)
                v.push_back(b == NA ? 0 : b + 1);
        }

        gt.dat.push_back(v);
    }

    gt.dist.assign(gt.loc.size(), 0.0);
    gt.ploidy = ploidy;

    return 0;
}

int write_vcf(const Genotype &gt, const string &filename, bool force_diploid)
{
    std::ofstream ofs(filename);
    if ( ! ofs ) {
        std::cerr << "ERROR: can't open file for writing: " << filename << "\n";
        return 1;
    }

    auto m = gt.loc.size(), n = gt.ind.size();
    bool haploid = gt.ploidy == 1;

    ofs << "##fileformat=VCFv4.2\n";
    ofs << "##filedate=" << datetime_now() << "\n";

    ofs << "#CHROM\tPOS\tID\tREF\tALT\tQUAL\tFILTER\tINFO";
    if ( ! gt.ind.empty() ) {
        ofs << "\tFORMAT";
        for (size_t i = 0; i < n; ++i)
            ofs << "\t" << gt.ind[i];
    }
    ofs << "\n";

    string line;

    for (size_t j = 0; j < m; ++j) {
        line.clear();

        line.append(gt.chr[j]).push_back('\t');
        line.append(std::to_string(gt.pos[j])).push_back('\t');
        line.append(gt.loc[j]).push_back('\t');

        if ( ! gt.allele[j].empty() ) {
            line.append(gt.allele[j][0]).push_back('\t');
            auto na = gt.allele[j].size();
            if (na > 1) {
                for (size_t k = 1; k < na; ++k)
                    line.append(gt.allele[j][k]).push_back(',');
                line.pop_back();
            }
            else
                line.push_back('.');
        }
        else
            line.append(".\t.");

        line.append("\t.\t.\t.");

        if ( gt.ind.empty() ) {
            ofs << line << "\n";
            continue;
        }

        line.append("\tGT");

        if ( haploid ) {
            if ( force_diploid ) {
                for (size_t i = 0; i < n; ++i) {
                    auto a = gt.dat[j][i];
                    string as = a == 0 ? "." : std::to_string(a-1);
                    line.append("\t").append(as).append("/").append(as);
                }
            }
            else {
                for (size_t i = 0; i < n; ++i) {
                    auto a = gt.dat[j][i];
                    line.push_back('\t');
                    line.append(a == 0 ? "." : std::to_string(a-1));
                }
            }
        }
        else {
            for (size_t i = 0; i < n; ++i) {
                auto a = gt.dat[j][i*2], b = gt.dat[j][i*2+1];
                line.push_back('\t');
                line.append(a == 0 ? "." : std::to_string(a-1));
                line.push_back('/');
                line.append(b == 0 ? "." : std::to_string(b-1));
            }
        }

        ofs << line << "\n";
    }

    return 0;
}
<commit_msg>Fixed typo<commit_after>#include <ctime>
#include <limits>
#include <fstream>
#include <iostream>
#include "vcfio.h"
#include "strsplit.h"
#include "util.h"

namespace {

const int NA = std::numeric_limits<int>::min();

// ret < 0: error; ret > 0 : ploidy
int parse_gt(const Token &t, int &a, int &b)
{
    string gt(t.data(), std::find(t.data(), t.data() + t.size(), ':'));

    if ( gt.empty() )
        return -1;

    if (gt == ".")
        return 1;

    if (gt == "./." || gt == ".|.")
        return 2;

    if (std::count(gt.begin(), gt.end(), '/') + std::count(gt.begin(), gt.end(), '|') > 1) {
        std::cerr << "ERROR: unsuppored polyploidy genotype: " << gt << "\n";
        return -1;
    }

    auto pos = gt.find_first_of("/|");
    if (pos == 0 || pos == gt.size() - 1)
        return -1;

    bool ok = false;

    if (pos == string::npos) {
        a = number<int>(gt, &ok);
        if ( ! ok || a < 0 )
            return -1;
        return 1;
    }

    auto sa = gt.substr(0,pos);
    if (sa != ".") {
        a = number<int>(sa, &ok);
        if ( ! ok || a < 0 )
            return -1;
    }

    auto sb = gt.substr(pos+1);
    if (sb != ".") {
        b = number<int>(sb, &ok);
        if ( ! ok || b < 0 )
            return -1;
    }

    return 2;
}

string datetime_now()
{
    char buf[16];
    auto t = std::time(nullptr);
    std::strftime(buf, sizeof(buf), "%Y%m%d%H%M%S", std::localtime(&t));
    return string(buf);
}

} // namespace

int read_vcf(const string &filename, Genotype &gt)
{
    std::ifstream ifs(filename);
    if ( ! ifs ) {
        std::cerr << "ERROR: can't open file for reading: " << filename << "\n";
        return 1;
    }

    auto delim = [](char c) { return c == ' ' || c == '\t' || c == '\r'; };

    size_t ln = 0;
    string ver;

    for (string line; std::getline(ifs,line); ) {
        ++ln;

        if (ln == 1 && line.compare(0,13,"##fileformat=") == 0) {
            ver = line.substr(13);
            if (ver != "VCFv4.0" && ver != "VCFv4.1" && ver != "VCFv4.2") {
                std::cerr << "ERROR: unsupported VCF format version: " << ver << "\n";
                return 1;
            }
        }

        if (line.compare(0,7,"##INFO=") == 0)
            continue;

        if (line.compare(0,9,"##FILTER=") == 0)
            continue;

        if (line.compare(0,9,"##FORMAT=") == 0)
            continue;

        if (line.compare(0,9,"##contig=") == 0)
            continue;

        if (line.compare(0,2,"##") == 0)
            continue;

        if (line.compare(0,1,"#") == 0) {
            vector<string> vs;
            strsplit(delim, line.begin(), line.end(), vs);

            if (vs.size() != 8 && vs.size() < 10) {
                std::cerr << "ERROR: incorrect number of columns in header line: " << vs.size() << "\n";
                return 1;
            }

            if (vs[0] != "#CHROM" || vs[1] != "POS" || vs[2] != "ID" || vs[3] != "REF" ||
                vs[4] != "ALT" || vs[5] != "QUAL" || vs[6] != "FILTER" || vs[7] != "INFO") {
                std::cerr << "ERROR: incorrect column names in header line: "
                          << vs[0] << "\t" << vs[1] << "\t" << vs[2] << "\t" << vs[3] << "\t"
                          << vs[4] << "\t" << vs[5] << "\t" << vs[6] << "\t" << vs[7] << "\n";
                return 1;
            }

            if (vs.size() > 9) {
                if (vs[8] != "FORMAT") {
                    std::cerr << "ERROR: FORMAT is required at 9th field in header line: " << vs[8] << "\n";
                    return 1;
                }
                gt.ind.assign(vs.begin() + 9, vs.end());
            }

            break;
        }

        std::cerr << "ERROR: #CHROME header line is required\n";
        return 1;
    }

    if ( ver.empty() ) {
        std::cerr << "ERROR: ##fileformat field is required and must be the first line\n";
        return 1;
    }

    int ploidy = -1;
    size_t ncols = gt.ind.empty() ? 8 : gt.ind.size() + 9;

    for (string line; std::getline(ifs,line); ) {
        ++ln;

        vector<Token> vt;
        strsplit(delim, line.begin(), line.end(), vt);

        if (vt.size() != ncols) {
            std::cerr << "ERROR: column count doesn't match at line " << ln << " (" << vt.size() << " != "
                      << ncols << "): " << filename << "\n";
            return 1;
        }

        gt.chr.push_back(string(vt[0]));
        gt.pos.push_back(number<int>(string(vt[1])));

        if (vt[2] == Token(".",1))
            gt.loc.push_back(string(vt[0]) + "_" + string(vt[1]));
        else
            gt.loc.push_back(string(vt[2]));

        if ( gt.ind.empty() )
            continue;

        auto format = string(vt[8]);
        if (format.compare(0,2,"GT") != 0) {
            std::cerr << "ERROR: GT is required and must be the first sub-field of FORMAT: " << format << "\n";
            return 1;
        }

        auto ref = string(vt[3]);
        auto alt = string(vt[4]);
        std::transform(ref.begin(), ref.end(), ref.begin(), ::toupper);
        std::transform(alt.begin(), alt.end(), alt.begin(), ::toupper);

        vector<string> as;
        as.push_back(ref);
        strsplit([](char c) { return c == ','; }, alt.begin(), alt.end(), as);
        gt.allele.push_back(as);
        int nas = as.size();

        vector<allele_t> v;
        for (size_t i = 9; i < ncols; ++i) {
            int a = NA, b = NA;
            int info = parse_gt(vt[i], a, b);
            if (info < 0 || a >= nas || b >= nas) {
                std::cerr << "ERROR: invalid genotype data: " << string(vt[i]) << "\n";
                return 1;
            }

            if (ploidy == -1)
                ploidy = info;

            if (info != ploidy) {
                std::cerr << "ERROR: inconsistent ploidy (" << ploidy << ") genotype: " << string(vt[i]) << "\n";
                return 1;
            }

            v.push_back(a == NA ? 0 : a + 1);
            if (ploidy == 2)
                v.push_back(b == NA ? 0 : b + 1);
        }

        gt.dat.push_back(v);
    }

    gt.dist.assign(gt.loc.size(), 0.0);
    gt.ploidy = ploidy;

    return 0;
}

int write_vcf(const Genotype &gt, const string &filename, bool force_diploid)
{
    std::ofstream ofs(filename);
    if ( ! ofs ) {
        std::cerr << "ERROR: can't open file for writing: " << filename << "\n";
        return 1;
    }

    auto m = gt.loc.size(), n = gt.ind.size();
    bool haploid = gt.ploidy == 1;

    ofs << "##fileformat=VCFv4.2\n";
    ofs << "##filedate=" << datetime_now() << "\n";

    ofs << "#CHROM\tPOS\tID\tREF\tALT\tQUAL\tFILTER\tINFO";
    if ( ! gt.ind.empty() ) {
        ofs << "\tFORMAT";
        for (size_t i = 0; i < n; ++i)
            ofs << "\t" << gt.ind[i];
    }
    ofs << "\n";

    string line;

    for (size_t j = 0; j < m; ++j) {
        line.clear();

        line.append(gt.chr[j]).push_back('\t');
        line.append(std::to_string(gt.pos[j])).push_back('\t');
        line.append(gt.loc[j]).push_back('\t');

        if ( ! gt.allele[j].empty() ) {
            line.append(gt.allele[j][0]).push_back('\t');
            auto na = gt.allele[j].size();
            if (na > 1) {
                for (size_t k = 1; k < na; ++k)
                    line.append(gt.allele[j][k]).push_back(',');
                line.pop_back();
            }
            else
                line.push_back('.');
        }
        else
            line.append(".\t.");

        line.append("\t.\t.\t.");

        if ( gt.ind.empty() ) {
            ofs << line << "\n";
            continue;
        }

        line.append("\tGT");

        if ( haploid ) {
            if ( force_diploid ) {
                for (size_t i = 0; i < n; ++i) {
                    auto a = gt.dat[j][i];
                    string as = a == 0 ? "." : std::to_string(a-1);
                    line.append("\t").append(as).append("/").append(as);
                }
            }
            else {
                for (size_t i = 0; i < n; ++i) {
                    auto a = gt.dat[j][i];
                    line.push_back('\t');
                    line.append(a == 0 ? "." : std::to_string(a-1));
                }
            }
        }
        else {
            for (size_t i = 0; i < n; ++i) {
                auto a = gt.dat[j][i*2], b = gt.dat[j][i*2+1];
                line.push_back('\t');
                line.append(a == 0 ? "." : std::to_string(a-1));
                line.push_back('/');
                line.append(b == 0 ? "." : std::to_string(b-1));
            }
        }

        ofs << line << "\n";
    }

    return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2010 Tommi Maekitalo
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * As a special exception, you may use this file as part of a free
 * software library without restriction. Specifically, if other files
 * instantiate templates or use macros or inline functions from this
 * file, or you compile this file and link it with other files to
 * produce an executable, this file does not by itself cause the
 * resulting executable to be covered by the GNU General Public
 * License. This exception does not however invalidate any other
 * reasons why the executable file might be covered by the GNU Library
 * General Public License.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <iostream>
#include <vector>
#include <string.h>
#include "cxxtools/arg.h"
#include "cxxtools/unit/testsuite.h"
#include "cxxtools/unit/registertest.h"

class ArgTest : public cxxtools::unit::TestSuite
{
        std::vector<char*> argp;

        char* arg(const char* value)
        {
            argp.push_back(new char [strlen(value) + 1]);
            strcpy(argp.back(), value);
            return argp.back();
        }

    public:
        ArgTest()
        : cxxtools::unit::TestSuite("cxxtools-arg-Test")
        {
            registerMethod("testArgBool", *this, &ArgTest::testArgBool);
            registerMethod("testArgCharP", *this, &ArgTest::testArgCharP);
            registerMethod("testArgpInt", *this, &ArgTest::testArgpInt);
            registerMethod("testArgpCharp", *this, &ArgTest::testArgpCharp);
            registerMethod("testArgpStdString", *this, &ArgTest::testArgpStdString);
        }

        void setUp()
        {
        }

        void tearDown()
        {
            for (std::vector<char*>::iterator it = argp.begin(); it != argp.end(); ++it)
                delete[] *it;
            argp.clear();
        }

        void testArgBool()
        {
            int argc = 7;
            char* argv[] = { arg("prog"), arg("-i"), arg("-j"), arg("-k"),
                arg("-cf"), arg("--foo"), arg("foo"), 0 };

            cxxtools::Arg<bool> optionJ(argc, argv, 'j');
            cxxtools::Arg<bool> optionL(argc, argv, 'l');
            cxxtools::Arg<bool> optionC(argc, argv, 'c');
            cxxtools::Arg<bool> optionFoo(argc, argv, "--foo");
            cxxtools::Arg<bool> optionBar(argc, argv, "--bar");

            CXXTOOLS_UNIT_ASSERT(optionJ);
            CXXTOOLS_UNIT_ASSERT(!optionL);
            CXXTOOLS_UNIT_ASSERT(optionC);
            CXXTOOLS_UNIT_ASSERT(optionFoo);
            CXXTOOLS_UNIT_ASSERT(!optionBar);
            CXXTOOLS_UNIT_ASSERT_EQUALS(argc, 5);
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(argv[0], "prog"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(argv[1], "-i"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(argv[2], "-k"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(argv[3], "-f"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(argv[4], "foo"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(argv[5], 0);
        }

        void testArgCharP()
        {
            int argc = 7;
            char* argv[] = { arg("prog"), arg("-i"), arg("foo"), arg("--foo"),
                arg("inp"), arg("-k"), arg("bar"), 0 };

            cxxtools::Arg<const char*> optionI(argc, argv, 'i');
            cxxtools::Arg<const char*> optionL(argc, argv, 'l', "blah");
            cxxtools::Arg<const char*> optionFoo(argc, argv, "--foo");
            cxxtools::Arg<const char*> optionBar(argc, argv, "--bar");

            CXXTOOLS_UNIT_ASSERT(optionI.isSet());
            CXXTOOLS_UNIT_ASSERT(!optionL.isSet());
            CXXTOOLS_UNIT_ASSERT(optionFoo.isSet());
            CXXTOOLS_UNIT_ASSERT(!optionBar.isSet());
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(optionI.getValue(), "foo"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(optionL.getValue(), "blah"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(optionFoo.getValue(), "inp"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(optionBar.getValue(), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(argc, 3);
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(argv[0], "prog"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(argv[1], "-k"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(argv[2], "bar"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(argv[3], 0);
        }

        void testArgpInt()
        {
            int argc = 6;
            char* argv[] = { arg("prog"), arg("-v"), arg("42"), arg("-i"), arg("-j5"), arg("--foo"), 0 };

            cxxtools::Arg<int> optionJ(argc, argv, 'j');
            cxxtools::Arg<int> optionV(argc, argv, 'v');

            CXXTOOLS_UNIT_ASSERT(optionJ.isSet());
            CXXTOOLS_UNIT_ASSERT(optionV.isSet());
            CXXTOOLS_UNIT_ASSERT_EQUALS(optionJ, 5);
            CXXTOOLS_UNIT_ASSERT_EQUALS(optionV, 42);
            CXXTOOLS_UNIT_ASSERT_EQUALS(argc, 3);
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(argv[0], "prog"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(argv[1], "-i"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(argv[2], "--foo"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(argv[3], 0);
        }

        void testArgpCharp()
        {
            int argc = 6;
            char* argv[] = { arg("prog"), arg("-v"), arg("42"), arg("-I"), arg("include"), arg("-Jfoo"), 0 };

            cxxtools::Arg<const char*> optionI(argc, argv, 'I');
            cxxtools::Arg<const char*> optionJ(argc, argv, 'J');

            CXXTOOLS_UNIT_ASSERT(optionI.isSet());
            CXXTOOLS_UNIT_ASSERT(optionJ.isSet());
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(optionI, "include"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(optionJ, "foo"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(argc, 3);
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(argv[0], "prog"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(argv[1], "-v"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(argv[2], "42"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(argv[3], 0);
        }

        void testArgpStdString()
        {
            int argc = 6;
            char* argv[] = { arg("prog"), arg("-v"), arg("42"), arg("-Jfoo"), arg("-I"), arg("include"), 0 };

            cxxtools::Arg<std::string> optionI(argc, argv, 'I');
            cxxtools::Arg<std::string> optionJ(argc, argv, 'J');

            CXXTOOLS_UNIT_ASSERT(optionI.isSet());
            CXXTOOLS_UNIT_ASSERT(optionJ.isSet());
            CXXTOOLS_UNIT_ASSERT_EQUALS(optionI.getValue(), "include");
            CXXTOOLS_UNIT_ASSERT_EQUALS(optionJ.getValue(), "foo");
            CXXTOOLS_UNIT_ASSERT_EQUALS(argc, 3);
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(argv[0], "prog"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(argv[1], "-v"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(argv[2], "42"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(argv[3], 0);
        }

};

cxxtools::unit::RegisterTest<ArgTest> register_ArgTest;
<commit_msg>add unit tests for parsing command line arguments with spaces<commit_after>/*
 * Copyright (C) 2010 Tommi Maekitalo
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * As a special exception, you may use this file as part of a free
 * software library without restriction. Specifically, if other files
 * instantiate templates or use macros or inline functions from this
 * file, or you compile this file and link it with other files to
 * produce an executable, this file does not by itself cause the
 * resulting executable to be covered by the GNU General Public
 * License. This exception does not however invalidate any other
 * reasons why the executable file might be covered by the GNU Library
 * General Public License.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <iostream>
#include <vector>
#include <string.h>
#include "cxxtools/arg.h"
#include "cxxtools/unit/testsuite.h"
#include "cxxtools/unit/registertest.h"

class ArgTest : public cxxtools::unit::TestSuite
{
        std::vector<char*> argp;

        char* arg(const char* value)
        {
            argp.push_back(new char [strlen(value) + 1]);
            strcpy(argp.back(), value);
            return argp.back();
        }

    public:
        ArgTest()
        : cxxtools::unit::TestSuite("cxxtools-arg-Test")
        {
            registerMethod("testArgBool", *this, &ArgTest::testArgBool);
            registerMethod("testArgCharP", *this, &ArgTest::testArgCharP);
            registerMethod("testArgpInt", *this, &ArgTest::testArgpInt);
            registerMethod("testArgpCharp", *this, &ArgTest::testArgpCharp);
            registerMethod("testArgpStdString", *this, &ArgTest::testArgpStdString);
        }

        void setUp()
        {
        }

        void tearDown()
        {
            for (std::vector<char*>::iterator it = argp.begin(); it != argp.end(); ++it)
                delete[] *it;
            argp.clear();
        }

        void testArgBool()
        {
            int argc = 7;
            char* argv[] = { arg("prog"), arg("-i"), arg("-j"), arg("-k"),
                arg("-cf"), arg("--foo"), arg("foo"), 0 };

            cxxtools::Arg<bool> optionJ(argc, argv, 'j');
            cxxtools::Arg<bool> optionL(argc, argv, 'l');
            cxxtools::Arg<bool> optionC(argc, argv, 'c');
            cxxtools::Arg<bool> optionFoo(argc, argv, "--foo");
            cxxtools::Arg<bool> optionBar(argc, argv, "--bar");

            CXXTOOLS_UNIT_ASSERT(optionJ);
            CXXTOOLS_UNIT_ASSERT(!optionL);
            CXXTOOLS_UNIT_ASSERT(optionC);
            CXXTOOLS_UNIT_ASSERT(optionFoo);
            CXXTOOLS_UNIT_ASSERT(!optionBar);
            CXXTOOLS_UNIT_ASSERT_EQUALS(argc, 5);
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(argv[0], "prog"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(argv[1], "-i"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(argv[2], "-k"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(argv[3], "-f"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(argv[4], "foo"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(argv[5], 0);
        }

        void testArgCharP()
        {
            int argc = 7;
            char* argv[] = { arg("prog"), arg("-i"), arg("foo"), arg("--foo"),
                arg("inp"), arg("-k"), arg("bar"), 0 };

            cxxtools::Arg<const char*> optionI(argc, argv, 'i');
            cxxtools::Arg<const char*> optionL(argc, argv, 'l', "blah");
            cxxtools::Arg<const char*> optionFoo(argc, argv, "--foo");
            cxxtools::Arg<const char*> optionBar(argc, argv, "--bar");

            CXXTOOLS_UNIT_ASSERT(optionI.isSet());
            CXXTOOLS_UNIT_ASSERT(!optionL.isSet());
            CXXTOOLS_UNIT_ASSERT(optionFoo.isSet());
            CXXTOOLS_UNIT_ASSERT(!optionBar.isSet());
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(optionI.getValue(), "foo"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(optionL.getValue(), "blah"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(optionFoo.getValue(), "inp"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(optionBar.getValue(), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(argc, 3);
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(argv[0], "prog"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(argv[1], "-k"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(argv[2], "bar"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(argv[3], 0);
        }

        void testArgpInt()
        {
            int argc = 6;
            char* argv[] = { arg("prog"), arg("-v"), arg("42"), arg("-i"), arg("-j5"), arg("--foo"), 0 };

            cxxtools::Arg<int> optionJ(argc, argv, 'j');
            cxxtools::Arg<int> optionV(argc, argv, 'v');

            CXXTOOLS_UNIT_ASSERT(optionJ.isSet());
            CXXTOOLS_UNIT_ASSERT(optionV.isSet());
            CXXTOOLS_UNIT_ASSERT_EQUALS(optionJ, 5);
            CXXTOOLS_UNIT_ASSERT_EQUALS(optionV, 42);
            CXXTOOLS_UNIT_ASSERT_EQUALS(argc, 3);
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(argv[0], "prog"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(argv[1], "-i"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(argv[2], "--foo"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(argv[3], 0);
        }

        void testArgpCharp()
        {
            int argc = 7;
            char* argv[] = { arg("prog"), arg("-v"), arg("42"),
                arg("-I"), arg("include"), arg("-Jfoo"), arg("-Khello world"), 0 };

            cxxtools::Arg<const char*> optionI(argc, argv, 'I');
            cxxtools::Arg<const char*> optionJ(argc, argv, 'J');
            cxxtools::Arg<const char*> optionK(argc, argv, 'K');

            CXXTOOLS_UNIT_ASSERT(optionI.isSet());
            CXXTOOLS_UNIT_ASSERT(optionJ.isSet());
            CXXTOOLS_UNIT_ASSERT(optionK.isSet());
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(optionI, "include"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(optionJ, "foo"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(optionK, "hello world"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(argc, 3);
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(argv[0], "prog"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(argv[1], "-v"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(argv[2], "42"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(argv[3], 0);
        }

        void testArgpStdString()
        {
            int argc = 7;
            char* argv[] = { arg("prog"), arg("-v"), arg("42"), arg("-Jfoo"),
                arg("-I"), arg("include"), arg("-Khello world"), 0 };

            cxxtools::Arg<std::string> optionI(argc, argv, 'I');
            cxxtools::Arg<std::string> optionJ(argc, argv, 'J');
            cxxtools::Arg<std::string> optionK(argc, argv, 'K');

            CXXTOOLS_UNIT_ASSERT(optionI.isSet());
            CXXTOOLS_UNIT_ASSERT(optionJ.isSet());
            CXXTOOLS_UNIT_ASSERT(optionK.isSet());
            CXXTOOLS_UNIT_ASSERT_EQUALS(optionI.getValue(), "include");
            CXXTOOLS_UNIT_ASSERT_EQUALS(optionJ.getValue(), "foo");
            CXXTOOLS_UNIT_ASSERT_EQUALS(optionK.getValue(), "hello world");
            CXXTOOLS_UNIT_ASSERT_EQUALS(argc, 3);
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(argv[0], "prog"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(argv[1], "-v"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(strcmp(argv[2], "42"), 0);
            CXXTOOLS_UNIT_ASSERT_EQUALS(argv[3], 0);
        }

};

cxxtools::unit::RegisterTest<ArgTest> register_ArgTest;
<|endoftext|>


<commit_before>#if ! defined (__CINT__) || defined (__MAKECINT__)
#include "TError.h"
#include <THnSparse.h>
#include <TObjArray.h>
#include <TObjString.h>
#include <TString.h>
#include <TROOT.h>
#include <TString.h>
#include <TSystem.h>
#include <TFile.h>
#include <TH2.h>
#endif

const Int_t ntasks(3);
const Char_t *taskConfig[]={
  "TRDefficiency_EFF"
  ,"TRDresolution_Cluster2Track:Tracklet2Track:Tracklet2TRDin:Cluster2MC:Tracklet2MC:TRDin2MC:TRD2MC"
  ,"TRDresolutionK_Cluster2Track:Tracklet2Track:Tracklet2TRDin:Cluster2MC:Tracklet2MC:TRDin2MC:TRD2MC"
};
Char_t taskName[ntasks][100]={{""}};
TObjArray *plots[ntasks] = {NULL};
THnSparse **H[ntasks]={NULL};
TObjArray *arr(NULL);
TFile *file(NULL);
void addPerformance(const Int_t it);
void mergeProdLocal(const Char_t *list)
{
  gSystem->Load("libANALYSIS.so");
  gSystem->Load("libANALYSISalice.so");
  gSystem->Load("libTender.so");
  gSystem->Load("libCORRFW.so");
  gSystem->Load("libPWGPP.so");

  FILE *fp(NULL);
  if(!(fp = fopen(list, "rt"))){
    Error("mergeProd.C", "Missing input list \"%s\".", list);
    return;
  }
  // read task descriptors
  TString s, s1;
  for(Int_t it(0); it<ntasks; it++){
    s=taskConfig[it];
    s1=s(0, s.Index('_')); sprintf(taskName[it], "%s", s1.Data());
    s = s(s.Index('_')+1, 200); plots[it] = s.Tokenize(":");
    H[it] = new THnSparse*[plots[it]->GetEntries()];
    memset(H[it], 0, plots[it]->GetEntries()*sizeof(THnSparse*));
  }
  TObjArray *infoGenArr(NULL);

  printf("Merging ");
  Char_t fn[200]; TString slist;
  while(slist.Gets(fp)){
    if(slist.EndsWith("zip")) snprintf(fn, 200, "%s#AnalysisResults.root", slist.Data());
    else if(slist.EndsWith("root")) snprintf(fn, 200, "%s", slist.Data());
    else{
      Warning("mergeProd", "Don't know what to do with file \"%s\". Skip file.", slist.Data());
      continue;
    }
    if(!(file = TFile::Open(fn))) continue;
    //Info("mergeProd", "Adding file %s ...", fn);
    printf(".");fflush(stdout);
    if(!file->cd("TRD_Performance")){
      Warning("mergeProd", "Missing TRD_Performance. Skip file.");
      continue;
    }

    if(!(arr = (TObjArray*)gDirectory->Get("TRDinfoGen"))){
      Warning("mergeProd", "Missing TRDinfoGen. Skip file.");
      continue;
    }
    if(!infoGenArr) infoGenArr=(TObjArray*)arr->Clone();
    else{
      ((TH1*)infoGenArr->At(0))->Add((TH1*)arr->At(0));
      ((TH1*)infoGenArr->At(1))->Add((TH1*)arr->At(1));
      ((TH2*)infoGenArr->At(2))->Add((TH2*)arr->At(2));
      //((AliTRDtriggerInfo*)infoGenArr->At(3))->Merge((AliTRDtriggerInfo*)arr->At(3));
    }
    for(Int_t itask(0); itask<ntasks; itask++){
      if(!(arr = (TObjArray*)gDirectory->Get(taskName[itask]))){
        Warning("mergeEntry", "Missing %s. Skip task.", taskName[itask]);
        continue;
      }
      addPerformance(itask);
    }
    file->Close();
    delete file;
  }

  slist=list;
  for(Int_t i(slist.Length()); --i;) {
    if(slist(i)!='.') continue;
    s1 = slist(0, i);
    snprintf(fn, 200, "Merged_%s.root", s1.Data());
    break;
  }
  printf("\nWritting to \"%s\"...\n", fn);
  TFile::Open(fn, "RECREATE");
  gFile->mkdir("TRD_Performance")->Write();
  gFile->cd("TRD_Performance");
  infoGenArr->Write("TRDinfoGen", 1);
  for(Int_t it(0); it<ntasks; it++){
    Int_t nplots(plots[it]->GetEntries());
    arr = new TObjArray(nplots); arr->SetOwner();
    for(Int_t ih(0); ih<nplots; ih++) arr->AddAt(H[it][ih], ih);
    arr->Write(taskName[it], 1);
  }
  gFile->Close();
}

void addPerformance(const Int_t it)
{
  THnSparse *h(NULL);
  Int_t nplots(plots[it]->GetEntries());
  char sname[50];
  for(Int_t ih(0); ih<nplots; ih++){
    snprintf(sname, 50, "h%s", ((TObjString*)(*plots[it])[ih])->GetName());
    if(!(h = (THnSparse*)arr->FindObject(sname))) {
      Warning("addPerformance", "Missing %s.", sname);
      continue;
    }
    gROOT->cd();
    if(H[it][ih]) H[it][ih]->Add(h);
    else H[it][ih] = (THnSparse*)h->Clone(sname);
    file->cd("TRD_Performance");
  }
}
<commit_msg>introduced flushing of merged files for the case of large productions<commit_after>#if ! defined (__CINT__) || defined (__MAKECINT__)
#include "TError.h"
#include <THnSparse.h>
#include <TObjArray.h>
#include <TObjString.h>
#include <TString.h>
#include <TROOT.h>
#include <TString.h>
#include <TSystem.h>
#include <TFile.h>
#include <TH2.h>
#endif

const Int_t ntasks(3);
const Char_t *taskConfig[]={
  "TRDefficiency_EFF"
  ,"TRDresolution_Cluster2Track:Tracklet2Track:Tracklet2TRDin:Cluster2MC:Tracklet2MC:TRDin2MC:TRD2MC"
  ,"TRDresolutionK_Cluster2Track:Tracklet2Track:Tracklet2TRDin:Cluster2MC:Tracklet2MC:TRDin2MC:TRD2MC"
};
Char_t taskName[ntasks][100]={{""}};
TObjArray *plots[ntasks] = {NULL};
TObjArray *arr(NULL), *narr[ntasks] = {NULL};
TFile *file(NULL), *fOut(NULL);
Bool_t mc(kFALSE),
       kWrite(kFALSE),
       kVerbose(kFALSE);
void addPerformance(const Int_t it);
void mergeProdLocal(const Char_t *list, Bool_t doMC=kFALSE, const Int_t nwrite=10000)
{
  gSystem->Load("libANALYSIS.so");
  gSystem->Load("libANALYSISalice.so");
  gSystem->Load("libTender.so");
  gSystem->Load("libCORRFW.so");
  gSystem->Load("libPWGPP.so");

  FILE *fp(NULL);
  if(!(fp = fopen(list, "rt"))){
    Error("mergeProd.C", "Missing input list \"%s\".", list);
    return;
  }
  printf("Usage : mergeProdLocal(list, doMC, n)\n"
    "  list : the list of AnalysisResults file to be merged. Files can be root or zip archived.\n"
    "       : using \"%s\".\n"
    "  doMC : true if production is MC. Default false.\n"
    "       : using \"%s\".\n"
    "  n    : Optional parameter to specify the number of files to be added until a flush of the\n"
    "         merged file is performed. Use only for large productions.\n"
    "       : using %d.\n", list, (doMC?"true":"false"), nwrite
  );

  // build out filename
  TString s, s1, slist=list;
  Char_t fn[200];
  for(Int_t i(slist.Length()); --i;) {
    if(slist(i)!='.') continue;
    s1 = slist(0, i);
    snprintf(fn, 200, "Merged_%s.root", s1.Data());
    break;
  }
  printf("Opening merged file \"%s\"...\n", fn);
  fOut = TFile::Open(fn, "RECREATE");
  fOut->mkdir("TRD_Performance")->Write();

  // read task descriptors a
  for(Int_t it(0); it<ntasks; it++){
    s=taskConfig[it];
    s1=s(0, s.Index('_')); sprintf(taskName[it], "%s", s1.Data());
    s = s(s.Index('_')+1, 200); plots[it] = s.Tokenize(":");
  }
  TObjArray *infoGenArr(NULL);
  mc = doMC;
  Int_t ifile(0);
  if(!kVerbose) printf("Merging ");
  while(slist.Gets(fp)){
    if(slist.EndsWith("zip")) snprintf(fn, 200, "%s#AnalysisResults.root", slist.Data());
    else if(slist.EndsWith("root")) snprintf(fn, 200, "%s", slist.Data());
    else{
      Warning("mergeProd", "Don't know what to do with file \"%s\". Skip file.", slist.Data());
      continue;
    }
    if(!(file = TFile::Open(fn))) continue;
    if(kVerbose) Info("mergeProd", "Adding file %s ...", fn);
    else printf(".");fflush(stdout);
    if(!file->cd("TRD_Performance")){
      Warning("mergeProd", "Missing TRD_Performance. Skip file.");
      continue;
    }

    if(!(arr = (TObjArray*)gDirectory->Get("TRDinfoGen"))){
      Warning("mergeProd", "Missing TRDinfoGen. Skip file.");
      continue;
    }

    if((ifile%nwrite)==(nwrite-1)){
      kWrite = kTRUE;
      if(!kVerbose) printf("\nMerging ");
      else printf(" ... Flushing merged file ...");
    }
    fOut->cd("TRD_Performance");
    if(!infoGenArr) infoGenArr=(TObjArray*)arr->Clone();
    else {
      ((TH1*)infoGenArr->At(0))->Add((TH1*)arr->At(0));
      ((TH1*)infoGenArr->At(1))->Add((TH1*)arr->At(1));
      ((TH2*)infoGenArr->At(2))->Add((TH2*)arr->At(2));
    }
    arr->Delete(); delete arr;

    for(Int_t itask(0); itask<ntasks; itask++){
      file->cd("TRD_Performance");
      if(!(arr = (TObjArray*)gDirectory->Get(taskName[itask]))){
        Warning("mergeEntry", "Missing %s. Skip task.", taskName[itask]);
        continue;
      }
      fOut->cd("TRD_Performance");
      addPerformance(itask);
      arr->Delete(); delete arr;
    }
    file->Close(); delete file;
    ifile++; kWrite = kFALSE;
    //if(ifile>=35) break;
  }

  if(!kVerbose) printf("\n");
  Info("mergeProd", "Flushing merged file ...");
  fOut->cd("TRD_Performance");
  if(infoGenArr) infoGenArr->Write("TRDinfoGen", TObject::kSingleKey);
  for(Int_t it(0); it<ntasks; it++){
    if(!(arr = (TObjArray*)gDirectory->Get(taskName[it]))) continue;
    arr->Write(taskName[it], TObject::kSingleKey);
  }
  fOut->Close();
}

void addPerformance(const Int_t it)
{
  if(!narr[it]){
    narr[it] = (TObjArray*)arr->Clone(); narr[it]->SetOwner();
    return;
  }

  THnSparse *h(NULL), *H(NULL);
  Int_t nplots(plots[it]->GetEntries());
  TString sname;
  for(Int_t ih(0); ih<nplots; ih++){
    sname= ((TObjString*)(*plots[it])[ih])->String();
    if(!mc && sname.EndsWith("MC")) continue;
    sname.Prepend("h");
    if(!(h = (THnSparse*)arr->FindObject(sname.Data()))) {
      Warning("addPerformance", "Missing %s. from \"%s\"", sname.Data(), file->GetName());
      continue;
    }
    if(!(H = (THnSparse*)narr[it]->FindObject(sname.Data()))) {
      Error("addPerformance", "Missing %s. from Merging.", sname.Data());
      return;
    }
    //printf("  -> %s[%d]\n", sname.Data(), (Int_t)H->GetEntries());
    H->Add(h);
  }
  if(kWrite){
    narr[it]->Write(taskName[it], /*TObject::kOverwrite|*/TObject::kSingleKey);
    narr[it]->Delete(); delete narr[it]; narr[it] = NULL;
  }
}
<|endoftext|>


<commit_before><commit_msg>updated nanoflann.hpp to avoid MSVC warnings<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2014 Ratcoin dev-team
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "addTrackerAction.h"
#include "common/setResponseVisitor.h"
#include "common/commonEvents.h"
#include "common/authenticationProvider.h"
#include "common/mediumRequests.h"

#include <boost/statechart/simple_state.hpp>
#include <boost/statechart/state.hpp>
#include <boost/statechart/transition.hpp>
#include <boost/statechart/custom_reaction.hpp>

namespace monitor
{

struct CBothUnidentifiedConnected;

struct CUninitiated : boost::statechart::simple_state< CUninitiated, CAddTrackerAction >
{
	typedef boost::mpl::list<
	boost::statechart::transition< common::CSwitchToConnectedEvent, CBothUnidentifiedConnected >
	> reactions;
};

template < class Parent >
void
createIdentifyResponse( Parent & parent )
{
	uint256 hash = Hash( &parent.getPayload().front(), &parent.getPayload().back() );

	std::vector< unsigned char > signedHash;
	common::CAuthenticationProvider::getInstance()->sign( hash, signedHash );

	parent.setRequest( new common::CIdentifyResponse< MonitorResponses >( parent.getMediumKind(), signedHash, common::CAuthenticationProvider::getInstance()->getMyKeyId(), parent.getPayload() ) );
}

struct CPairIdentifiedConnected : boost::statechart::state< CPairIdentifiedConnected, CAddTrackerAction >
{
	CPairIdentifiedConnected( my_context ctx ) : my_base( ctx )
	{
		context< CAddTrackerAction >().setRequest( 0 );
	}
};

struct CBothUnidentifiedConnected : boost::statechart::state< CBothUnidentifiedConnected, CAddTrackerAction >
{
	CBothUnidentifiedConnected( my_context ctx ) : my_base( ctx )
	{
		common::CIntroduceEvent const* requestedEvent = dynamic_cast< common::CIntroduceEvent const* >( simple_state::triggering_event() );

		createIdentifyResponse( context< CAddTrackerAction >() );

	}

	boost::statechart::result react( const common::CContinueEvent & _continueEvent )
	{
		context< CAddTrackerAction >().setRequest( new common::CContinueReqest< MonitorResponses >( _continueEvent.m_keyId, context< CAddTrackerAction >().getMediumKind() ) );
	}

	typedef boost::mpl::list<
	boost::statechart::transition< common::CIntroduceEvent, CPairIdentifiedConnected >,
	boost::statechart::custom_reaction< common::CContinueEvent >
	> reactions;
};

CAddTrackerAction::CAddTrackerAction( std::vector< unsigned char > const & _payload, unsigned int _mediumKind )
{
}

common::CRequest< MonitorResponses >*
CAddTrackerAction::execute()
{
	return 0;
}

std::vector< unsigned char >
CAddTrackerAction::getPayload() const
{
	return m_payload;
}

unsigned int
CAddTrackerAction::getMediumKind() const
{
	return m_mediumKind;
}

void
CAddTrackerAction::setMediumKind( unsigned int _mediumKind )
{
	m_mediumKind = _mediumKind;
}

void
CAddTrackerAction::accept( common::CSetResponseVisitor< MonitorResponses > & _visitor )
{
	_visitor.visit( *this );
}

void
CAddTrackerAction::setRequest( common::CRequest< MonitorResponses >* _request )
{
	m_request = _request;
}

}
<commit_msg>debugging <commit_after>// Copyright (c) 2014 Ratcoin dev-team
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "addTrackerAction.h"
#include "common/setResponseVisitor.h"
#include "common/commonEvents.h"
#include "common/authenticationProvider.h"
#include "common/mediumRequests.h"

#include <boost/statechart/simple_state.hpp>
#include <boost/statechart/state.hpp>
#include <boost/statechart/transition.hpp>
#include <boost/statechart/custom_reaction.hpp>

namespace monitor
{

struct CBothUnidentifiedConnected;

struct CUninitiated : boost::statechart::simple_state< CUninitiated, CAddTrackerAction >
{
	typedef boost::mpl::list<
	boost::statechart::transition< common::CSwitchToConnectedEvent, CBothUnidentifiedConnected >
	> reactions;
};

template < class Parent >
void
createIdentifyResponse( Parent & parent )
{
	uint256 hash = Hash( &parent.getPayload().front(), &parent.getPayload().back() );

	std::vector< unsigned char > signedHash;
	common::CAuthenticationProvider::getInstance()->sign( hash, signedHash );

	parent.setRequest( new common::CIdentifyResponse< MonitorResponses >( parent.getMediumKind(), signedHash, common::CAuthenticationProvider::getInstance()->getMyKeyId(), parent.getPayload() ) );
}

struct CPairIdentifiedConnected : boost::statechart::state< CPairIdentifiedConnected, CAddTrackerAction >
{
	CPairIdentifiedConnected( my_context ctx ) : my_base( ctx )
	{
		context< CAddTrackerAction >().setRequest( 0 );
	}
};

struct CBothUnidentifiedConnected : boost::statechart::state< CBothUnidentifiedConnected, CAddTrackerAction >
{
	CBothUnidentifiedConnected( my_context ctx ) : my_base( ctx )
	{
		common::CIntroduceEvent const* requestedEvent = dynamic_cast< common::CIntroduceEvent const* >( simple_state::triggering_event() );

		createIdentifyResponse( context< CAddTrackerAction >() );

	}

	boost::statechart::result react( const common::CContinueEvent & _continueEvent )
	{
		context< CAddTrackerAction >().setRequest( new common::CContinueReqest< MonitorResponses >( _continueEvent.m_keyId, context< CAddTrackerAction >().getMediumKind() ) );
	}

	typedef boost::mpl::list<
	boost::statechart::transition< common::CIntroduceEvent, CPairIdentifiedConnected >,
	boost::statechart::custom_reaction< common::CContinueEvent >
	> reactions;
};

CAddTrackerAction::CAddTrackerAction( std::vector< unsigned char > const & _payload, unsigned int _mediumKind )
{
	initiate();
	process_event( common::CSwitchToConnectedEvent() );
}

common::CRequest< MonitorResponses >*
CAddTrackerAction::execute()
{
	return m_request;
}

std::vector< unsigned char >
CAddTrackerAction::getPayload() const
{
	return m_payload;
}

unsigned int
CAddTrackerAction::getMediumKind() const
{
	return m_mediumKind;
}

void
CAddTrackerAction::setMediumKind( unsigned int _mediumKind )
{
	m_mediumKind = _mediumKind;
}

void
CAddTrackerAction::accept( common::CSetResponseVisitor< MonitorResponses > & _visitor )
{
	_visitor.visit( *this );
}

void
CAddTrackerAction::setRequest( common::CRequest< MonitorResponses >* _request )
{
	m_request = _request;
}

}
<|endoftext|>


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

#include <iterator>

#include <type_traits>

namespace gnr
{

namespace detail
{

template <typename T>
class rev_impl
{
  T ref_;

public:
  explicit rev_impl(T&& r) noexcept :
    ref_(std::forward<T>(r))
  {
  };

  auto begin() const noexcept(noexcept(std::rbegin(ref_)))
  {
    return std::rbegin(std::forward<T>(ref_));
  }

  auto end() const noexcept(noexcept(std::rend(ref_)))
  {
    return std::rend(std::forward<T>(ref_));
  }

  auto cbegin() const noexcept(noexcept(std::crbegin(ref_)))
  {
    return std::crbegin(std::forward<T>(ref_));
  }

  auto cend() const noexcept(noexcept(std::crend(ref_)))
  {
    return std::crend(std::forward<T>(ref_));
  }
};

}

template <typename T, typename = std::enable_if_t<std::is_reference<T>{}>>
auto rev(T&& ref) noexcept(noexcept(
  detail::rev_impl<T&&>(std::forward<T>(ref))))
{
  return detail::rev_impl<T&&>(std::forward<T>(ref));
}

}

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

#include <iterator>

#include <type_traits>

namespace gnr
{

namespace detail
{

template <typename T>
class rev_impl
{
  T ref_;

public:
  explicit rev_impl(T&& r) noexcept :
    ref_(std::forward<T>(r))
  {
  };

  auto begin() const noexcept(noexcept(std::rbegin(ref_)))
  {
    return std::rbegin(std::forward<T>(ref_));
  }

  auto end() const noexcept(noexcept(std::rend(ref_)))
  {
    return std::rend(std::forward<T>(ref_));
  }

  auto cbegin() const noexcept(noexcept(std::crbegin(ref_)))
  {
    return std::crbegin(std::forward<T>(ref_));
  }

  auto cend() const noexcept(noexcept(std::crend(ref_)))
  {
    return std::crend(std::forward<T>(ref_));
  }
};

}

template <typename T, typename = std::enable_if_t<std::is_reference<T>{}>>
auto rev(T&& r) noexcept(noexcept(detail::rev_impl<T>(std::forward<T>(r))))
{
  return detail::rev_impl<T>(std::forward<T>(r));
}

}

#endif // GENERIC_REV_HPP
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
 *     Copyright 2010 Couchbase, Inc
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>

#include "libforestdb/forestdb.h"
#include "common.h"
#include "internal_types.h"
#include "btree_var_kv_ops.h"
#include "hbtrie.h"

#include "memleak.h"

#ifdef __DEBUG
#ifndef __DEBUG_FDB
    #undef DBG
    #undef DBGCMD
    #undef DBGSW
    #define DBG(...)
    #define DBGCMD(...)
    #define DBGSW(n, ...)
#endif
#endif

LIBFDB_API
fdb_status fdb_get_kv(fdb_kvs_handle *handle,
                      void *key, size_t keylen,
                      void **value_out, size_t *valuelen_out)
{
    fdb_doc *doc = NULL;
    fdb_status fs;

    if (key == NULL || keylen == 0 || keylen > FDB_MAX_KEYLEN ||
        value_out == NULL || valuelen_out == NULL ||
        (handle->kvs_config.custom_cmp &&
            keylen > handle->config.blocksize - HBTRIE_HEADROOM)) {
        return FDB_RESULT_INVALID_ARGS;
    }

    fs = fdb_doc_create(&doc, key, keylen, NULL, 0, NULL, 0);
    if (fs != FDB_RESULT_SUCCESS) {
        if (doc) { // LCOV_EXCL_START
            fdb_doc_free(doc);
        }
        return fs;
    } // LCOV_EXCL_STOP

    fs = fdb_get(handle, doc);
    if (fs != FDB_RESULT_SUCCESS) {
        if (doc) {
            fdb_doc_free(doc);
        }
        return fs;
    }

    *value_out = doc->body;
    *valuelen_out = doc->bodylen;
    if (doc->key) free(doc->key);
    if (doc->meta) free(doc->meta);
    free(doc);

    return fs;
}

LIBFDB_API
fdb_status fdb_set_kv(fdb_kvs_handle *handle,
                      void *key, size_t keylen,
                      void *value, size_t valuelen)
{
    fdb_doc *doc;
    fdb_status fs;

    if (key == NULL || keylen == 0 || keylen > FDB_MAX_KEYLEN ||
        (handle->kvs_config.custom_cmp &&
            keylen > handle->config.blocksize - HBTRIE_HEADROOM)) {
        return FDB_RESULT_INVALID_ARGS;
    }

    fs = fdb_doc_create(&doc, key, keylen, NULL, 0, value, valuelen);
    if (fs != FDB_RESULT_SUCCESS) {
        if (doc) { // LCOV_EXCL_START
            fdb_doc_free(doc);
        }
        return fs;
    } // LCOV_EXCL_STOP

    fs = fdb_set(handle, doc);
    if (fs != FDB_RESULT_SUCCESS) {
        if (doc) {
            fdb_doc_free(doc);
        }
        return fs;
    }
    fdb_doc_free(doc);

    return fs;
}

LIBFDB_API
fdb_status fdb_del_kv(fdb_kvs_handle *handle,
                      void *key, size_t keylen)
{
    fdb_doc *doc;
    fdb_status fs;

    if (key == NULL || keylen == 0 || keylen > FDB_MAX_KEYLEN ||
        (handle->kvs_config.custom_cmp &&
            keylen > handle->config.blocksize - HBTRIE_HEADROOM)) {
        return FDB_RESULT_INVALID_ARGS;
    }

    fs = fdb_doc_create(&doc, key, keylen, NULL, 0, NULL, 0);
    if (fs != FDB_RESULT_SUCCESS) {
        if (doc) { // LCOV_EXCL_START
            fdb_doc_free(doc);
        }
        return fs;
    } // LCOV_EXCL_STOP

    fs = fdb_del(handle, doc);
    if (fs != FDB_RESULT_SUCCESS) {
        fdb_doc_free(doc);
        return fs;
    }
    fdb_doc_free(doc);

    return fs;
}

LIBFDB_API
fdb_status fdb_free_block(void *ptr)
{
    free(ptr);
    return FDB_RESULT_SUCCESS;
}

<commit_msg>Add more loggings to erroneous cases in api_wrapper implementation<commit_after>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
 *     Copyright 2010 Couchbase, Inc
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>

#include "libforestdb/forestdb.h"
#include "common.h"
#include "internal_types.h"
#include "btree_var_kv_ops.h"
#include "hbtrie.h"
#include "fdb_internal.h"

#include "memleak.h"

#ifdef __DEBUG
#ifndef __DEBUG_FDB
    #undef DBG
    #undef DBGCMD
    #undef DBGSW
    #define DBG(...)
    #define DBGCMD(...)
    #define DBGSW(n, ...)
#endif
#endif

LIBFDB_API
fdb_status fdb_get_kv(fdb_kvs_handle *handle,
                      void *key, size_t keylen,
                      void **value_out, size_t *valuelen_out)
{
    fdb_doc *doc = NULL;
    fdb_status fs;

    if (key == NULL || keylen == 0 || keylen > FDB_MAX_KEYLEN ||
        value_out == NULL || valuelen_out == NULL ||
        (handle->kvs_config.custom_cmp &&
            keylen > handle->config.blocksize - HBTRIE_HEADROOM)) {
        return FDB_RESULT_INVALID_ARGS;
    }

    fs = fdb_doc_create(&doc, key, keylen, NULL, 0, NULL, 0);
    if (fs != FDB_RESULT_SUCCESS) { // LCOV_EXCL_START
        if (doc) {
            fdb_doc_free(doc);
        }
        fdb_log(&handle->log_callback, fs,
                "Warning: Failed to allocate fdb_doc instance for key '%s' in "
                "fdb_get_kv API.", (const char *)key);
        return fs;
    } // LCOV_EXCL_STOP

    fs = fdb_get(handle, doc);
    if (fs != FDB_RESULT_SUCCESS) {
        if (doc) {
            fdb_doc_free(doc);
        }
        return fs;
    }

    *value_out = doc->body;
    *valuelen_out = doc->bodylen;
    if (doc->key) free(doc->key);
    if (doc->meta) free(doc->meta);
    free(doc);

    return fs;
}

LIBFDB_API
fdb_status fdb_set_kv(fdb_kvs_handle *handle,
                      void *key, size_t keylen,
                      void *value, size_t valuelen)
{
    fdb_doc *doc;
    fdb_status fs;

    if (key == NULL || keylen == 0 || keylen > FDB_MAX_KEYLEN ||
        (handle->kvs_config.custom_cmp &&
            keylen > handle->config.blocksize - HBTRIE_HEADROOM)) {
        return FDB_RESULT_INVALID_ARGS;
    }

    fs = fdb_doc_create(&doc, key, keylen, NULL, 0, value, valuelen);
    if (fs != FDB_RESULT_SUCCESS) { // LCOV_EXCL_START
        if (doc) {
            fdb_doc_free(doc);
        }
        fdb_log(&handle->log_callback, fs,
                "Warning: Failed to allocate fdb_doc instance for key '%s' in "
                "fdb_set_kv API.", (const char *)key);
        return fs;
    } // LCOV_EXCL_STOP

    fs = fdb_set(handle, doc);
    if (fs != FDB_RESULT_SUCCESS) {
        if (doc) {
            fdb_doc_free(doc);
        }
        return fs;
    }
    fdb_doc_free(doc);

    return fs;
}

LIBFDB_API
fdb_status fdb_del_kv(fdb_kvs_handle *handle,
                      void *key, size_t keylen)
{
    fdb_doc *doc;
    fdb_status fs;

    if (key == NULL || keylen == 0 || keylen > FDB_MAX_KEYLEN ||
        (handle->kvs_config.custom_cmp &&
            keylen > handle->config.blocksize - HBTRIE_HEADROOM)) {
        return FDB_RESULT_INVALID_ARGS;
    }

    fs = fdb_doc_create(&doc, key, keylen, NULL, 0, NULL, 0);
    if (fs != FDB_RESULT_SUCCESS) { // LCOV_EXCL_START
        if (doc) {
            fdb_doc_free(doc);
        }
        fdb_log(&handle->log_callback, fs,
                "Warning: Failed to allocate fdb_doc instance for key '%s' in "
                "fdb_del_kv API.", (const char *)key);
        return fs;
    } // LCOV_EXCL_STOP

    fs = fdb_del(handle, doc);
    if (fs != FDB_RESULT_SUCCESS) {
        fdb_doc_free(doc);
        return fs;
    }
    fdb_doc_free(doc);

    return fs;
}

LIBFDB_API
fdb_status fdb_free_block(void *ptr)
{
    free(ptr);
    return FDB_RESULT_SUCCESS;
}

<|endoftext|>