<commit_before>/*
 * eos - A 3D Morphable Model fitting library written in modern C++11/14.
 *
 * File: include/eos/morphablemodel/PcaModel.hpp
 *
 * Copyright 2014-2017 Patrik Huber
 *
 * 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.
 */
#pragma once

#ifndef PCAMODEL_HPP_
#define PCAMODEL_HPP_

#include "eos/morphablemodel/io/eigen_cerealisation.hpp"
#include "cereal/access.hpp"
#include "cereal/types/array.hpp"
#include "cereal/types/vector.hpp"

#include "Eigen/Core"

#include "opencv2/core/core.hpp"

#include <string>
#include <vector>
#include <array>
#include <random>
#include <cassert>

namespace eos {
	namespace morphablemodel {

// Forward declarations of free functions:
Eigen::MatrixXf rescale_pca_basis(const Eigen::MatrixXf& orthonormal_basis, const Eigen::VectorXf& eigenvalues);
Eigen::MatrixXf normalise_pca_basis(const Eigen::MatrixXf& rescaled_basis, const Eigen::VectorXf& eigenvalues);

/**
 * @brief This class represents a PCA-model that consists of:
 *   - a mean vector (y x z)
 *   - a PCA basis matrix (orthonormal and rescaled)
 *   - a PCA variance vector.
 *
 * It also contains a list of triangles to built a mesh as well as a mapping
 * from landmark points to the corresponding vertex-id in the mesh.
 */
class PcaModel
{
public:
	PcaModel() = default;

	/**
	 * Construct a PCA model from given mean, normalised PCA basis, eigenvalues
	 * and triangle list.
	 *
	 * See the documentation of the member variables for how the data should
	 * be arranged.
	 *
	 * @param[in] mean The mean used to build the PCA model.
	 * @param[in] orthonormal_pca_basis An orthonormal PCA basis (eigenvectors).
	 * @param[in] eigenvalues The eigenvalues used to build the PCA model.
	 * @param[in] triangle_list An index list of how to assemble the mesh.
	 */
	PcaModel(Eigen::VectorXf mean, Eigen::MatrixXf orthonormal_pca_basis, Eigen::VectorXf eigenvalues, std::vector<std::array<int, 3>> triangle_list) : mean(mean), orthonormal_pca_basis(orthonormal_pca_basis), eigenvalues(eigenvalues), triangle_list(triangle_list)
	{
		rescaled_pca_basis = rescale_pca_basis(orthonormal_pca_basis, eigenvalues);
	};

	/**
	 * Returns the number of principal components in the model.
	 *
	 * @return The number of principal components in the model.
	 */
	int get_num_principal_components() const
	{
		// Note: we could assert(rescaled_pca_basis.cols==orthonormal_pca_basis.cols)
		return rescaled_pca_basis.cols();
	};

	/**
	 * Returns the dimension of the data, i.e. the number of shape dimensions.
	 *
	 * As the data is arranged in a [x y z x y z ...] fashion, dividing this by
	 * three yields the number of vertices in the model.
	 *
	 * @return The dimension of the data.
	 */
	int get_data_dimension() const
	{
		// Note: we could assert(rescaled_pca_basis.rows==orthonormal_pca_basis.rows)
		return rescaled_pca_basis.rows();
	};

	/**
	 * Returns a list of triangles on how to assemble the vertices into a mesh.
	 *
	 * @return The list of triangles to build a mesh.
	 */
	std::vector<std::array<int, 3>> get_triangle_list() const
	{
		return triangle_list;
	};

	/**
	 * Returns the mean of the model.
	 *
	 * @return The mean of the model.
	 */
	const Eigen::VectorXf& get_mean() const
	{
		return mean;
	};

	/**
	 * Return the value of the mean at a given vertex index.
	 *
	 * I think we should just return an Eigen::Vector3f - homogenous coords have no place here?
	 *
	 * @param[in] vertex_index A vertex index.
	 * @return A homogeneous vector containing the values at the given vertex index.
	 */
	cv::Vec4f get_mean_at_point(int vertex_index) const
	{
		vertex_index *= 3;
		return cv::Vec4f(mean(vertex_index), mean(vertex_index + 1), mean(vertex_index + 2), 1.0f);
	};

	/**
	 * Draws a random sample from the model, where the coefficients are drawn
	 * from a standard normal (or with the given standard deviation).
	 *
	 * @param[in] engine Random number engine used to draw random coefficients.
	 * @param[in] sigma The standard deviation.
	 * @return A random sample from the model.
	 */
	template <class RNG>
	Eigen::VectorXf draw_sample(RNG& engine, float sigma = 1.0f) const
	{
		std::normal_distribution<float> distribution(0.0f, sigma); // this constructor takes the stddev

		std::vector<float> alphas(get_num_principal_components());

		for (auto&& a : alphas) {
			a = distribution(engine);
		}

		return draw_sample(alphas);
	};

	/**
	 * Returns a sample from the model with the given PCA coefficients.
	 * The given coefficients should follow a standard normal distribution, i.e.
	 * not be "normalised" with their eigenvalues/variances.
	 *
	 * @param[in] coefficients The PCA coefficients used to generate the sample.
	 * @return A model instance with given coefficients.
	 */
	Eigen::VectorXf draw_sample(std::vector<float> coefficients) const
	{
		// Fill the rest with zeros if not all coefficients are given:
		if (coefficients.size() < get_num_principal_components()) {
			coefficients.resize(get_num_principal_components());
		}
		Eigen::Map<Eigen::VectorXf> alphas(coefficients.data(), coefficients.size());

		Eigen::VectorXf model_sample = mean + rescaled_pca_basis * alphas;

		return model_sample;
	};

	/**
	 * @copydoc PcaModel::draw_sample(std::vector<float>) const
	 */
	Eigen::VectorXf draw_sample(std::vector<double> coefficients) const
	{
		// We have to convert the vector of doubles to float:
		std::vector<float> coeffs_float(std::begin(coefficients), std::end(coefficients));
		return draw_sample(coeffs_float);
	};

	/**
	 * Returns the PCA basis matrix, i.e. the eigenvectors.
	 * Each column of the matrix is an eigenvector.
	 * The returned basis is rescaled, i.e. every eigenvector
	 * is rescaled by multiplying it with the square root of its eigenvalue.
	 *
	 * @return Returns the rescaled PCA basis matrix.
	 */
	const Eigen::MatrixXf& get_rescaled_pca_basis() const
	{
		return rescaled_pca_basis;
	};

	/**
	 * Returns the PCA basis for a particular vertex, from the rescaled basis.
	 *
	 * Note: The function does not return the i-th basis vector - it returns all basis
	 * vectors, but only the block that is relevant for the vertex \p vertex_id.
	 *
	 * Todo: Can we return a const & view that points into the original data?
	 *
	 * @param[in] vertex_id A vertex index. Make sure it is valid.
	 * @return A 1x3? 3x1? matrix that points to the rows in the original basis.
	 */
	Eigen::MatrixXf get_rescaled_pca_basis_at_point(int vertex_id) const
	{
		vertex_id *= 3; // the basis is stored in the format [x y z x y z ...]
		assert(vertex_id < get_data_dimension()); // Make sure the given vertex index isn't larger than the number of model vertices.
		return rescaled_pca_basis.block(vertex_id, 0, 3, rescaled_pca_basis.cols());
	};

	/**
	 * Returns the PCA basis matrix, i.e. the eigenvectors.
	 * Each column of the matrix is an eigenvector.
	 * The returned basis is orthonormal, i.e. the eigenvectors
	 * are not scaled by their respective eigenvalues.
	 *
	 * @return Returns the orthonormal PCA basis matrix.
	 */
	const Eigen::MatrixXf& get_orthonormal_pca_basis() const
	{
		return orthonormal_pca_basis;
	};

	/**
	 * Returns the PCA basis for a particular vertex, from the orthonormal basis.
	 *
	 * Note: The function does not return the i-th basis vector - it returns all basis
	 * vectors, but only the block that is relevant for the vertex \p vertex_id.
	 *
	 * @param[in] vertex_id A vertex index. Make sure it is valid.
	 * @return A matrix that points to the rows in the original basis.
	 */
	Eigen::MatrixXf get_orthonormal_pca_basis_at_point(int vertex_id) const
	{
		vertex_id *= 3; // the basis is stored in the format [x y z x y z ...]
		assert(vertex_id < get_data_dimension()); // Make sure the given vertex index isn't larger than the number of model vertices.
		return orthonormal_pca_basis.block(vertex_id, 0, 3, orthonormal_pca_basis.cols());
	};

	/**
	 * Returns the models eigenvalues.
	 *
	 * @return The eigenvalues.
	 */
	const Eigen::VectorXf& get_eigenvalues() const
	{
		return eigenvalues;
	};

	/**
	 * Returns a specific eigenvalue.
	 *
	 * @param[in] index The index of the eigenvalue to return.
	 * @return The eigenvalue.
	 */
	float get_eigenvalue(int index) const
	{
		// no assert - Eigen checks access with an assert in debug builds
		return eigenvalues(index);
	};

private:
	Eigen::VectorXf mean; ///< A 3m x 1 col-vector (xyzxyz...)', where m is the number of model-vertices.
	Eigen::MatrixXf orthonormal_pca_basis; ///< m x n (rows x cols) = numShapeDims x numShapePcaCoeffs, (=eigenvector matrix V). Each column is an eigenvector.
	Eigen::MatrixXf rescaled_pca_basis; ///< m x n (rows x cols) = numShapeDims x numShapePcaCoeffs, (=eigenvector matrix V). Each column is an eigenvector.
	Eigen::VectorXf eigenvalues; ///< A col-vector of the eigenvalues (variances in the PCA space).

	std::vector<std::array<int, 3>> triangle_list; ///< List of triangles that make up the mesh of the model.

	friend class cereal::access;
	/**
	 * Serialises this class using cereal.
	 *
	 * @param[in] archive The archive to serialise to (or to serialise from).
	 */
	template <class Archive>
	void serialize(Archive& archive)
	{
		archive(CEREAL_NVP(mean), CEREAL_NVP(orthonormal_pca_basis), CEREAL_NVP(eigenvalues), CEREAL_NVP(triangle_list));
		// If we're loading, we have to recompute the rescaled basis, so that it's available (we don't store it anymore):
		if (Archive::is_loading::value)
		{
			rescaled_pca_basis = rescale_pca_basis(orthonormal_pca_basis, eigenvalues);
		}
	};
};

/**
 * Takes an orthonormal PCA basis matrix (a matrix consisting
 * of the eigenvectors) and rescales it, i.e. multiplies each
 * eigenvector by the square root of its corresponding
 * eigenvalue.
 *
 * @param[in] orthonormal_basis An orthonormal_basis PCA basis matrix.
 * @param[in] eigenvalues A row or column vector of eigenvalues.
 * @return The rescaled PCA basis matrix.
 */
inline Eigen::MatrixXf rescale_pca_basis(const Eigen::MatrixXf& orthonormal_basis, const Eigen::VectorXf& eigenvalues)
{
	using Eigen::MatrixXf;
	MatrixXf rescaled_basis(orthonormal_basis.rows(), orthonormal_basis.cols()); // empty matrix with the same dimensions
	MatrixXf sqrt_of_eigenvalues = eigenvalues.array().sqrt(); // using eigenvalues.sqrt() directly gives a compile error. These are all Eigen::Array functions? I don't think we copy here, do we?
	// Rescale the basis: We multiply each eigenvector (i.e. each column) with the square root of its corresponding eigenvalue
	for (int basis = 0; basis < orthonormal_basis.cols(); ++basis) {
		rescaled_basis.col(basis) = orthonormal_basis.col(basis) * sqrt_of_eigenvalues(basis);
	}

	return rescaled_basis;
};

/**
 * Takes a rescaled PCA basis matrix and scales it back to
 * an orthonormal basis matrix by multiplying each eigenvector
 * by 1 over the square root of its corresponding eigenvalue.
 *
 * @param[in] rescaled_basis A rescaled PCA basis matrix.
 * @param[in] eigenvalues A row or column vector of eigenvalues.
 * @return The orthonormal PCA basis matrix.
 */
inline Eigen::MatrixXf normalise_pca_basis(const Eigen::MatrixXf& rescaled_basis, const Eigen::VectorXf& eigenvalues)
{
	using Eigen::MatrixXf;
	MatrixXf orthonormal_basis(rescaled_basis.rows(), rescaled_basis.cols()); // empty matrix with the same dimensions
	Eigen::VectorXf one_over_sqrt_of_eigenvalues = eigenvalues.array().sqrt().inverse(); // Eigen added Array::rsqrt() in 3.3, switch back to that eventually
	// De-normalise the basis: We multiply each eigenvector (i.e. each column) with 1 over the square root of its corresponding eigenvalue
	for (int basis = 0; basis < rescaled_basis.cols(); ++basis) {
		orthonormal_basis.col(basis) = rescaled_basis.col(basis) * one_over_sqrt_of_eigenvalues(basis);
	}

	return orthonormal_basis;
};

	} /* namespace morphablemodel */
} /* namespace eos */

#endif /* PCAMODEL_HPP_ */
<commit_msg>Change get_mean_at_point() to return an Eigen::Vector3f<commit_after>/*
 * eos - A 3D Morphable Model fitting library written in modern C++11/14.
 *
 * File: include/eos/morphablemodel/PcaModel.hpp
 *
 * Copyright 2014-2017 Patrik Huber
 *
 * 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.
 */
#pragma once

#ifndef PCAMODEL_HPP_
#define PCAMODEL_HPP_

#include "eos/morphablemodel/io/eigen_cerealisation.hpp"
#include "cereal/access.hpp"
#include "cereal/types/array.hpp"
#include "cereal/types/vector.hpp"

#include "Eigen/Core"

#include <string>
#include <vector>
#include <array>
#include <random>
#include <cassert>

namespace eos {
	namespace morphablemodel {

// Forward declarations of free functions:
Eigen::MatrixXf rescale_pca_basis(const Eigen::MatrixXf& orthonormal_basis, const Eigen::VectorXf& eigenvalues);
Eigen::MatrixXf normalise_pca_basis(const Eigen::MatrixXf& rescaled_basis, const Eigen::VectorXf& eigenvalues);

/**
 * @brief This class represents a PCA-model that consists of:
 *   - a mean vector (y x z)
 *   - a PCA basis matrix (orthonormal and rescaled)
 *   - a PCA variance vector.
 *
 * It also contains a list of triangles to built a mesh as well as a mapping
 * from landmark points to the corresponding vertex-id in the mesh.
 */
class PcaModel
{
public:
	PcaModel() = default;

	/**
	 * Construct a PCA model from given mean, normalised PCA basis, eigenvalues
	 * and triangle list.
	 *
	 * See the documentation of the member variables for how the data should
	 * be arranged.
	 *
	 * @param[in] mean The mean used to build the PCA model.
	 * @param[in] orthonormal_pca_basis An orthonormal PCA basis (eigenvectors).
	 * @param[in] eigenvalues The eigenvalues used to build the PCA model.
	 * @param[in] triangle_list An index list of how to assemble the mesh.
	 */
	PcaModel(Eigen::VectorXf mean, Eigen::MatrixXf orthonormal_pca_basis, Eigen::VectorXf eigenvalues, std::vector<std::array<int, 3>> triangle_list) : mean(mean), orthonormal_pca_basis(orthonormal_pca_basis), eigenvalues(eigenvalues), triangle_list(triangle_list)
	{
		rescaled_pca_basis = rescale_pca_basis(orthonormal_pca_basis, eigenvalues);
	};

	/**
	 * Returns the number of principal components in the model.
	 *
	 * @return The number of principal components in the model.
	 */
	int get_num_principal_components() const
	{
		// Note: we could assert(rescaled_pca_basis.cols==orthonormal_pca_basis.cols)
		return rescaled_pca_basis.cols();
	};

	/**
	 * Returns the dimension of the data, i.e. the number of shape dimensions.
	 *
	 * As the data is arranged in a [x y z x y z ...] fashion, dividing this by
	 * three yields the number of vertices in the model.
	 *
	 * @return The dimension of the data.
	 */
	int get_data_dimension() const
	{
		// Note: we could assert(rescaled_pca_basis.rows==orthonormal_pca_basis.rows)
		return rescaled_pca_basis.rows();
	};

	/**
	 * Returns a list of triangles on how to assemble the vertices into a mesh.
	 *
	 * @return The list of triangles to build a mesh.
	 */
	std::vector<std::array<int, 3>> get_triangle_list() const
	{
		return triangle_list;
	};

	/**
	 * Returns the mean of the model.
	 *
	 * @return The mean of the model.
	 */
	const Eigen::VectorXf& get_mean() const
	{
		return mean;
	};

	/**
	 * Return the value of the mean at a given vertex index.
	 *
	 * @param[in] vertex_index A vertex index.
	 * @return A 3-dimensional vector containing the values at the given vertex index.
	 */
	Eigen::Vector3f get_mean_at_point(int vertex_index) const
	{
		vertex_index *= 3;
		// Note: We could maybe also return a const& to mean.block(...).
		return Eigen::Vector3f(mean(vertex_index), mean(vertex_index + 1), mean(vertex_index + 2));
	};

	/**
	 * Draws a random sample from the model, where the coefficients are drawn
	 * from a standard normal (or with the given standard deviation).
	 *
	 * @param[in] engine Random number engine used to draw random coefficients.
	 * @param[in] sigma The standard deviation.
	 * @return A random sample from the model.
	 */
	template <class RNG>
	Eigen::VectorXf draw_sample(RNG& engine, float sigma = 1.0f) const
	{
		std::normal_distribution<float> distribution(0.0f, sigma); // this constructor takes the stddev

		std::vector<float> alphas(get_num_principal_components());

		for (auto&& a : alphas) {
			a = distribution(engine);
		}

		return draw_sample(alphas);
	};

	/**
	 * Returns a sample from the model with the given PCA coefficients.
	 * The given coefficients should follow a standard normal distribution, i.e.
	 * not be "normalised" with their eigenvalues/variances.
	 *
	 * @param[in] coefficients The PCA coefficients used to generate the sample.
	 * @return A model instance with given coefficients.
	 */
	Eigen::VectorXf draw_sample(std::vector<float> coefficients) const
	{
		// Fill the rest with zeros if not all coefficients are given:
		if (coefficients.size() < get_num_principal_components()) {
			coefficients.resize(get_num_principal_components());
		}
		Eigen::Map<Eigen::VectorXf> alphas(coefficients.data(), coefficients.size());

		Eigen::VectorXf model_sample = mean + rescaled_pca_basis * alphas;

		return model_sample;
	};

	/**
	 * @copydoc PcaModel::draw_sample(std::vector<float>) const
	 */
	Eigen::VectorXf draw_sample(std::vector<double> coefficients) const
	{
		// We have to convert the vector of doubles to float:
		std::vector<float> coeffs_float(std::begin(coefficients), std::end(coefficients));
		return draw_sample(coeffs_float);
	};

	/**
	 * Returns the PCA basis matrix, i.e. the eigenvectors.
	 * Each column of the matrix is an eigenvector.
	 * The returned basis is rescaled, i.e. every eigenvector
	 * is rescaled by multiplying it with the square root of its eigenvalue.
	 *
	 * @return Returns the rescaled PCA basis matrix.
	 */
	const Eigen::MatrixXf& get_rescaled_pca_basis() const
	{
		return rescaled_pca_basis;
	};

	/**
	 * Returns the PCA basis for a particular vertex, from the rescaled basis.
	 *
	 * Note: The function does not return the i-th basis vector - it returns all basis
	 * vectors, but only the block that is relevant for the vertex \p vertex_id.
	 *
	 * Todo: Can we return a const & view that points into the original data?
	 *
	 * @param[in] vertex_id A vertex index. Make sure it is valid.
	 * @return A 1x3? 3x1? matrix that points to the rows in the original basis.
	 */
	Eigen::MatrixXf get_rescaled_pca_basis_at_point(int vertex_id) const
	{
		vertex_id *= 3; // the basis is stored in the format [x y z x y z ...]
		assert(vertex_id < get_data_dimension()); // Make sure the given vertex index isn't larger than the number of model vertices.
		return rescaled_pca_basis.block(vertex_id, 0, 3, rescaled_pca_basis.cols());
	};

	/**
	 * Returns the PCA basis matrix, i.e. the eigenvectors.
	 * Each column of the matrix is an eigenvector.
	 * The returned basis is orthonormal, i.e. the eigenvectors
	 * are not scaled by their respective eigenvalues.
	 *
	 * @return Returns the orthonormal PCA basis matrix.
	 */
	const Eigen::MatrixXf& get_orthonormal_pca_basis() const
	{
		return orthonormal_pca_basis;
	};

	/**
	 * Returns the PCA basis for a particular vertex, from the orthonormal basis.
	 *
	 * Note: The function does not return the i-th basis vector - it returns all basis
	 * vectors, but only the block that is relevant for the vertex \p vertex_id.
	 *
	 * @param[in] vertex_id A vertex index. Make sure it is valid.
	 * @return A matrix that points to the rows in the original basis.
	 */
	Eigen::MatrixXf get_orthonormal_pca_basis_at_point(int vertex_id) const
	{
		vertex_id *= 3; // the basis is stored in the format [x y z x y z ...]
		assert(vertex_id < get_data_dimension()); // Make sure the given vertex index isn't larger than the number of model vertices.
		return orthonormal_pca_basis.block(vertex_id, 0, 3, orthonormal_pca_basis.cols());
	};

	/**
	 * Returns the models eigenvalues.
	 *
	 * @return The eigenvalues.
	 */
	const Eigen::VectorXf& get_eigenvalues() const
	{
		return eigenvalues;
	};

	/**
	 * Returns a specific eigenvalue.
	 *
	 * @param[in] index The index of the eigenvalue to return.
	 * @return The eigenvalue.
	 */
	float get_eigenvalue(int index) const
	{
		// no assert - Eigen checks access with an assert in debug builds
		return eigenvalues(index);
	};

private:
	Eigen::VectorXf mean; ///< A 3m x 1 col-vector (xyzxyz...)', where m is the number of model-vertices.
	Eigen::MatrixXf orthonormal_pca_basis; ///< m x n (rows x cols) = numShapeDims x numShapePcaCoeffs, (=eigenvector matrix V). Each column is an eigenvector.
	Eigen::MatrixXf rescaled_pca_basis; ///< m x n (rows x cols) = numShapeDims x numShapePcaCoeffs, (=eigenvector matrix V). Each column is an eigenvector.
	Eigen::VectorXf eigenvalues; ///< A col-vector of the eigenvalues (variances in the PCA space).

	std::vector<std::array<int, 3>> triangle_list; ///< List of triangles that make up the mesh of the model.

	friend class cereal::access;
	/**
	 * Serialises this class using cereal.
	 *
	 * @param[in] archive The archive to serialise to (or to serialise from).
	 */
	template <class Archive>
	void serialize(Archive& archive)
	{
		archive(CEREAL_NVP(mean), CEREAL_NVP(orthonormal_pca_basis), CEREAL_NVP(eigenvalues), CEREAL_NVP(triangle_list));
		// If we're loading, we have to recompute the rescaled basis, so that it's available (we don't store it anymore):
		if (Archive::is_loading::value)
		{
			rescaled_pca_basis = rescale_pca_basis(orthonormal_pca_basis, eigenvalues);
		}
	};
};

/**
 * Takes an orthonormal PCA basis matrix (a matrix consisting
 * of the eigenvectors) and rescales it, i.e. multiplies each
 * eigenvector by the square root of its corresponding
 * eigenvalue.
 *
 * @param[in] orthonormal_basis An orthonormal_basis PCA basis matrix.
 * @param[in] eigenvalues A row or column vector of eigenvalues.
 * @return The rescaled PCA basis matrix.
 */
inline Eigen::MatrixXf rescale_pca_basis(const Eigen::MatrixXf& orthonormal_basis, const Eigen::VectorXf& eigenvalues)
{
	using Eigen::MatrixXf;
	MatrixXf rescaled_basis(orthonormal_basis.rows(), orthonormal_basis.cols()); // empty matrix with the same dimensions
	MatrixXf sqrt_of_eigenvalues = eigenvalues.array().sqrt(); // using eigenvalues.sqrt() directly gives a compile error. These are all Eigen::Array functions? I don't think we copy here, do we?
	// Rescale the basis: We multiply each eigenvector (i.e. each column) with the square root of its corresponding eigenvalue
	for (int basis = 0; basis < orthonormal_basis.cols(); ++basis) {
		rescaled_basis.col(basis) = orthonormal_basis.col(basis) * sqrt_of_eigenvalues(basis);
	}

	return rescaled_basis;
};

/**
 * Takes a rescaled PCA basis matrix and scales it back to
 * an orthonormal basis matrix by multiplying each eigenvector
 * by 1 over the square root of its corresponding eigenvalue.
 *
 * @param[in] rescaled_basis A rescaled PCA basis matrix.
 * @param[in] eigenvalues A row or column vector of eigenvalues.
 * @return The orthonormal PCA basis matrix.
 */
inline Eigen::MatrixXf normalise_pca_basis(const Eigen::MatrixXf& rescaled_basis, const Eigen::VectorXf& eigenvalues)
{
	using Eigen::MatrixXf;
	MatrixXf orthonormal_basis(rescaled_basis.rows(), rescaled_basis.cols()); // empty matrix with the same dimensions
	Eigen::VectorXf one_over_sqrt_of_eigenvalues = eigenvalues.array().sqrt().inverse(); // Eigen added Array::rsqrt() in 3.3, switch back to that eventually
	// De-normalise the basis: We multiply each eigenvector (i.e. each column) with 1 over the square root of its corresponding eigenvalue
	for (int basis = 0; basis < rescaled_basis.cols(); ++basis) {
		orthonormal_basis.col(basis) = rescaled_basis.col(basis) * one_over_sqrt_of_eigenvalues(basis);
	}

	return orthonormal_basis;
};

	} /* namespace morphablemodel */
} /* namespace eos */

#endif /* PCAMODEL_HPP_ */
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2013 Artem Pavlenko
 *
 * 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.
 *
 * 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 St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_HARFBUZZ_SHAPER_HPP
#define MAPNIK_HARFBUZZ_SHAPER_HPP

// mapnik
#include <mapnik/text/text_properties.hpp>
#include <mapnik/text/text_line.hpp>
#include <mapnik/text/face.hpp>
// stl
#include <list>

// harfbuzz
#include <harfbuzz/hb.h>
#include <harfbuzz/hb-ft.h>
#include <harfbuzz/hb-icu.h>

namespace mapnik
{

struct harfbuzz_shaper
{
static void shape_text(text_line & line,
                       text_itemizer & itemizer,
                       std::map<unsigned,double> & width_map,
                       face_manager_freetype & font_manager,
                       double scale_factor )
{
    unsigned start = line.first_char();
    unsigned end = line.last_char();
    mapnik::value_unicode_string const& text = itemizer.text();
    size_t length = end - start;
    if (!length) return;
    line.reserve(length);
    std::list<text_item> const& list = itemizer.itemize(start, end);

    auto hb_buffer_deleter = [](hb_buffer_t * buffer) { hb_buffer_destroy(buffer);};
    const std::unique_ptr<hb_buffer_t, decltype(hb_buffer_deleter)> buffer(hb_buffer_create(),hb_buffer_deleter);
    hb_buffer_set_unicode_funcs(buffer.get(), hb_icu_get_unicode_funcs());
    hb_buffer_pre_allocate(buffer.get(), length);

    for (auto const& text_item : list)
    {
        face_set_ptr face_set = font_manager.get_face_set(text_item.format->face_name, text_item.format->fontset);
        double size = text_item.format->text_size * scale_factor;
        face_set->set_unscaled_character_sizes();
        font_face_set::iterator face_itr = face_set->begin(), face_end = face_set->end();
        for (; face_itr != face_end; ++face_itr)
        {
            hb_buffer_clear_contents(buffer.get());
            hb_buffer_add_utf16(buffer.get(), text.getBuffer(), text.length(), text_item.start, text_item.end - text_item.start);
            hb_buffer_set_direction(buffer.get(), (text_item.rtl == UBIDI_RTL)?HB_DIRECTION_RTL:HB_DIRECTION_LTR);
            hb_buffer_set_script(buffer.get(), hb_icu_script_to_script(text_item.script));
            face_ptr const& face = *face_itr;
            hb_font_t *font(hb_ft_font_create(face->get_face(), nullptr));
            hb_shape(font, buffer.get(), nullptr, 0);
            hb_font_destroy(font);

            unsigned num_glyphs = hb_buffer_get_length(buffer.get());

            hb_glyph_info_t *glyphs = hb_buffer_get_glyph_infos(buffer.get(), nullptr);
            hb_glyph_position_t *positions = hb_buffer_get_glyph_positions(buffer.get(), nullptr);

            bool font_has_all_glyphs = true;
            // Check if all glyphs are valid.
            for (unsigned i=0; i<num_glyphs; ++i)
            {
                if (!glyphs[i].codepoint)
                {
                    font_has_all_glyphs = false;
                    break;
                }
            }
            if (!font_has_all_glyphs && face_itr+1 != face_end)
            {
                //Try next font in fontset
                continue;
            }

            for (unsigned i=0; i<num_glyphs; ++i)
            {
                glyph_info tmp;
                tmp.glyph_index = glyphs[i].codepoint;
                if (face->glyph_dimensions(tmp))
                {
                    tmp.char_index = glyphs[i].cluster;
                    tmp.face = face;
                    tmp.format = text_item.format;
                    tmp.scale_multiplier = size / face->get_face()->units_per_EM;
                    //Overwrite default advance with better value provided by HarfBuzz
                    tmp.unscaled_advance = positions[i].x_advance;

                    tmp.offset.set(positions[i].x_offset * tmp.scale_multiplier, positions[i].y_offset * tmp.scale_multiplier);
                    width_map[glyphs[i].cluster] += tmp.advance();
                    line.add_glyph(std::move(tmp), scale_factor);
                }
            }
            line.update_max_char_height(face->get_char_height(size));
            break; //When we reach this point the current font had all glyphs.
        }
    }
}
};
} // namespace mapnik

#endif // MAPNIK_HARFBUZZ_SHAPER_HPP
<commit_msg>c++11 style in harfbuzz_shaper.hpp<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2013 Artem Pavlenko
 *
 * 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.
 *
 * 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 St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_HARFBUZZ_SHAPER_HPP
#define MAPNIK_HARFBUZZ_SHAPER_HPP

// mapnik
#include <mapnik/text/text_properties.hpp>
#include <mapnik/text/text_line.hpp>
#include <mapnik/text/face.hpp>
// stl
#include <list>

// harfbuzz
#include <harfbuzz/hb.h>
#include <harfbuzz/hb-ft.h>
#include <harfbuzz/hb-icu.h>

namespace mapnik
{

struct harfbuzz_shaper
{
static void shape_text(text_line & line,
                       text_itemizer & itemizer,
                       std::map<unsigned,double> & width_map,
                       face_manager_freetype & font_manager,
                       double scale_factor )
{
    unsigned start = line.first_char();
    unsigned end = line.last_char();
    size_t length = end - start;
    if (!length) return;
    line.reserve(length);
    std::list<text_item> const& list = itemizer.itemize(start, end);

    auto hb_buffer_deleter = [](hb_buffer_t * buffer) { hb_buffer_destroy(buffer);};
    const std::unique_ptr<hb_buffer_t, decltype(hb_buffer_deleter)> buffer(hb_buffer_create(),hb_buffer_deleter);
    hb_buffer_set_unicode_funcs(buffer.get(), hb_icu_get_unicode_funcs());
    hb_buffer_pre_allocate(buffer.get(), length);
    mapnik::value_unicode_string const& text = itemizer.text();

    for (auto const& text_item : list)
    {
        face_set_ptr face_set = font_manager.get_face_set(text_item.format->face_name, text_item.format->fontset);
        double size = text_item.format->text_size * scale_factor;
        face_set->set_unscaled_character_sizes();
        std::size_t num_faces = face_set->size();
        std::size_t pos = 0;
        for (auto const& face : *face_set)
        {
            ++pos;
            hb_buffer_clear_contents(buffer.get());
            hb_buffer_add_utf16(buffer.get(), text.getBuffer(), text.length(), text_item.start, text_item.end - text_item.start);
            hb_buffer_set_direction(buffer.get(), (text_item.rtl == UBIDI_RTL)?HB_DIRECTION_RTL:HB_DIRECTION_LTR);
            hb_buffer_set_script(buffer.get(), hb_icu_script_to_script(text_item.script));
            hb_font_t *font(hb_ft_font_create(face->get_face(), nullptr));
            hb_shape(font, buffer.get(), nullptr, 0);
            hb_font_destroy(font);

            unsigned num_glyphs = hb_buffer_get_length(buffer.get());

            hb_glyph_info_t *glyphs = hb_buffer_get_glyph_infos(buffer.get(), nullptr);
            hb_glyph_position_t *positions = hb_buffer_get_glyph_positions(buffer.get(), nullptr);

            bool font_has_all_glyphs = true;
            // Check if all glyphs are valid.
            for (unsigned i=0; i<num_glyphs; ++i)
            {
                if (!glyphs[i].codepoint)
                {
                    font_has_all_glyphs = false;
                    break;
                }
            }
            if (!font_has_all_glyphs && (pos < num_faces))
            {
                //Try next font in fontset
                continue;
            }

            for (unsigned i=0; i<num_glyphs; ++i)
            {
                glyph_info tmp;
                tmp.glyph_index = glyphs[i].codepoint;
                if (face->glyph_dimensions(tmp))
                {
                    tmp.char_index = glyphs[i].cluster;
                    tmp.face = face;
                    tmp.format = text_item.format;
                    tmp.scale_multiplier = size / face->get_face()->units_per_EM;
                    //Overwrite default advance with better value provided by HarfBuzz
                    tmp.unscaled_advance = positions[i].x_advance;

                    tmp.offset.set(positions[i].x_offset * tmp.scale_multiplier, positions[i].y_offset * tmp.scale_multiplier);
                    width_map[glyphs[i].cluster] += tmp.advance();
                    line.add_glyph(std::move(tmp), scale_factor);
                }
            }
            line.update_max_char_height(face->get_char_height(size));
            break; //When we reach this point the current font had all glyphs.
        }
    }
}
};
} // namespace mapnik

#endif // MAPNIK_HARFBUZZ_SHAPER_HPP
<|endoftext|>


<commit_before>/**This file is part of powercores, released under the terms of the Unlicense.
See LICENSE in the root of the powercores repository for details.*/
#pragma once
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>
#include <queue>
#include <atomic>
#include "exceptions.hpp"

namespace powercores {
/**A threadsafe queue supporting any number of readers and writers.

Note: T must be default constructible, copy assignable and copy constructible.*/
template <typename T>
class ThreadsafeQueue {
	public:
	/**Enqueue an item.*/
	void enqueue(T item) {
		auto l = std::unique_lock<std::mutex>(lock);
		internal_queue.push_front(item);
		_size++;
		enqueued_notify.notify_one();
	}

	/**Dequeue an item.
If there is no item in the queue, this function sleeps forever.*/
	T dequeue() {
		auto l = std::unique_lock<std::mutex>(lock);
		if(internal_queue.empty() == false) {
			return actualDequeue();
		}

		enqueued_notify.wait(l, [this]() {return internal_queue.empty() == false;});
		return actualDequeue();
	}

	/**Like dequeue, but will throw TimeoutException if there is nothing to dequeue before the timeout.*/
	T dequeueWithTimeout(int timeoutInMS) {
		auto l = std::unique_lock<std::mutex>(lock);
		if(internal_queue.empty() == false) {
			return actualDequeue();
		}
		bool res = enqueued_notify.wait_for(l, std::chrono::milliseconds(timeoutInMS), [this]() {return internal_queue.empty() == false;});
		if(res) return actualDequeue();
		else throw TimeoutException();
	}

	/**Enqueue a range represented by the iterator begin and end.*/
	template<class IterT>
	void enqueueRange(IterT begin, IterT end) {
		auto l = std::unique_lock<std::mutex>(lock);
		for(; begin != end; begin++) internal_queue.push_front(*begin);
	}

	/**DequeueRange dequeues at least one item and at most the specified count, storing them in the iterator.
	The number of items dequeued is returned.*/
	template<class IterT>
	int dequeueRange(int count, IterT output) {
		auto l = std::unique_lock<std::mutex>(lock);
		int ret = 0;
		if(internal_queue.empty()) enqueued_notify.wait(l, [this] () {return internal_queue.empty() == false;});
		while(ret < count && internal_queue.empty() == false) {
			*output = actualDequeue();
			ret++;
			output++;
		}
		return ret;
	}

	bool empty() {
		auto l = std::lock_guard<std::mutex>(lock);
		return internal_queue.empty();
	}

/**Get the current number of items in the queue.*/
	unsigned int size() {
		auto l = std::lock_guard<std::mutex>(lock);
		return _size;
	}

	private:
	T actualDequeue() {
		auto res = internal_queue.back();
		internal_queue.pop_back();
		_size--;
		return res;
	}

	std::mutex lock;
	std::deque<T> internal_queue;
	std::condition_variable enqueued_notify;
	unsigned int _size = 0;
};

}
<commit_msg>Don't try to use the copy and/or move constructor of lock_guard.<commit_after>/**This file is part of powercores, released under the terms of the Unlicense.
See LICENSE in the root of the powercores repository for details.*/
#pragma once
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>
#include <queue>
#include <atomic>
#include "exceptions.hpp"

namespace powercores {
/**A threadsafe queue supporting any number of readers and writers.

Note: T must be default constructible, copy assignable and copy constructible.*/
template <typename T>
class ThreadsafeQueue {
	public:
	/**Enqueue an item.*/
	void enqueue(T item) {
		std::unique_lock<std::mutex> l(lock);
		internal_queue.push_front(item);
		_size++;
		enqueued_notify.notify_one();
	}

	/**Dequeue an item.
If there is no item in the queue, this function sleeps forever.*/
	T dequeue() {
		std::unique_lock<std::mutex> l(lock);
		if(internal_queue.empty() == false) {
			return actualDequeue();
		}

		enqueued_notify.wait(l, [this]() {return internal_queue.empty() == false;});
		return actualDequeue();
	}

	/**Like dequeue, but will throw TimeoutException if there is nothing to dequeue before the timeout.*/
	T dequeueWithTimeout(int timeoutInMS) {
		std::unique_lock<std::mutex> l(lock);
		if(internal_queue.empty() == false) {
			return actualDequeue();
		}
		bool res = enqueued_notify.wait_for(l, std::chrono::milliseconds(timeoutInMS), [this]() {return internal_queue.empty() == false;});
		if(res) return actualDequeue();
		else throw TimeoutException();
	}

	/**Enqueue a range represented by the iterator begin and end.*/
	template<class IterT>
	void enqueueRange(IterT begin, IterT end) {
		std::unique_lock<std::mutex> l(lock);
		for(; begin != end; begin++) internal_queue.push_front(*begin);
	}

	/**DequeueRange dequeues at least one item and at most the specified count, storing them in the iterator.
	The number of items dequeued is returned.*/
	template<class IterT>
	int dequeueRange(int count, IterT output) {
		std::unique_lock<std::mutex> l(lock);
		int ret = 0;
		if(internal_queue.empty()) enqueued_notify.wait(l, [this] () {return internal_queue.empty() == false;});
		while(ret < count && internal_queue.empty() == false) {
			*output = actualDequeue();
			ret++;
			output++;
		}
		return ret;
	}

	bool empty() {
		std::lock_guard<std::mutex> l(lock);
		return internal_queue.empty();
	}

/**Get the current number of items in the queue.*/
	unsigned int size() {
		std::lock_guard<std::mutex> l(lock);
		return _size;
	}

	private:
	T actualDequeue() {
		auto res = internal_queue.back();
		internal_queue.pop_back();
		_size--;
		return res;
	}

	std::mutex lock;
	std::deque<T> internal_queue;
	std::condition_variable enqueued_notify;
	unsigned int _size = 0;
};

}
<|endoftext|>


<commit_before>#ifndef VSMC_UTILITY_PROGRAM_OPTION_HPP
#define VSMC_UTILITY_PROGRAM_OPTION_HPP

#include <vsmc/internal/common.hpp>

#define VSMC_RUNTIME_ASSERT_UTILITY_PROGRAM_OPTION_NULLPTR(ptr, func) \
    VSMC_RUNTIME_ASSERT((bool(ptr)),                                         \
            ("**vsmc::ProgramOptionMap::"#func                               \
             "** ATTEMPT TO SET OPTION WITH A NULL POINTER"))

namespace vsmc {

/// \brief Program option base class
/// \ingroup Option
class ProgramOptionBase
{
    public :

    ProgramOptionBase () {}
    ProgramOptionBase (const ProgramOptionBase &) {}
    ProgramOptionBase &operator= (const ProgramOptionBase &) {return *this;}

    virtual bool set (std::stringstream &, const std::string &,
            const std::string &) = 0;
    virtual bool set_default () = 0;
    virtual void print_help (const std::string &) const = 0;
    virtual ProgramOptionBase *clone () const = 0;
    virtual ~ProgramOptionBase () {}

    protected :

    template <typename T>
    bool set_value (std::stringstream &ss, const std::string &oname,
            const std::string &sval, T *dest)
    {
        ss.clear();
        ss.str(sval);
        T tval;
        ss >> tval;
        if (ss.fail()) {
            std::fprintf(stderr,
                    "Failed to set value of option '%s': %s\n",
                    oname.c_str(), sval.c_str());
            ss.clear();
            return false;
        }
#if VSMC_HAS_CXX11_RVALUE_REFERENCES
        *dest = cxx11::move(tval);
#else
        *dest = tval;
#endif

        return true;
    }
}; // class ProgramOptionBase

/// \brief Opiton with a default value
/// \ingroup Option
template <typename T>
class ProgramOptionDefault : public ProgramOptionBase
{
    public :

    ProgramOptionDefault (const std::string &desc) :
        desc_(desc), default_(T()), has_default_(false) {}

    template <typename V>
    ProgramOptionDefault (const std::string &desc, const V &val) :
        desc_(desc), default_(static_cast<T>(val)), has_default_(true) {}

    void print_help (const std::string &oname) const
    {
        std::cout << "  " << std::setw(20) << std::left << oname << desc_;
        if (has_default_)
            std::cout << " (default: " << default_ << ")";
        std::cout << std::endl;
    }

    protected :

    bool set_value_default (T *dest)
    {
        if (has_default_)
            *dest = default_;

        return has_default_;
    }

    private :

    std::string desc_;
    T default_;
    bool has_default_;
}; // ProgramOptionDefault

/// \brief Option with a single value
/// \ingroup Option
template <typename T>
class ProgramOptionScalar : public ProgramOptionDefault<T>
{
    public :

    ProgramOptionScalar (const std::string &desc, T *ptr) :
        ProgramOptionDefault<T>(desc), ptr_(ptr) {}

    template <typename V>
    ProgramOptionScalar (const std::string &desc, T *ptr, const V &val) :
        ProgramOptionDefault<T>(desc, val), ptr_(ptr) {}

    bool set (std::stringstream &ss, const std::string &oname,
            const std::string &sval)
    {return this->set_value(ss, oname, sval, ptr_);}

    bool set_default () {return this->set_value_default(ptr_);}

    ProgramOptionBase *clone () const
    {
        ProgramOptionBase *ptr = new ProgramOptionScalar<T>(*this);

        return ptr;
    }

    private :

    T *const ptr_;
}; // class ProgramOptionScalar

/// \brief Option with multiple values
/// \ingroup Option
template <typename T>
class ProgramOptionVector : public ProgramOptionDefault<T>
{
    public :

    ProgramOptionVector (const std::string &desc, std::vector<T> *ptr) :
        ProgramOptionDefault<T>(desc), val_(T()), ptr_(ptr) {}

    template <typename V>
    ProgramOptionVector (const std::string &desc, std::vector<T> *ptr,
            const V &val) :
        ProgramOptionDefault<T>(desc, val), val_(T()), ptr_(ptr) {}

    bool set (std::stringstream &ss, const std::string &oname,
            const std::string &sval)
    {
        bool success = this->set_value(ss, oname, sval, &val_);

        if (success)
            ptr_->push_back(val_);

        return success;
    }

    bool set_default ()
    {
        bool success = this->set_value_default(&val_);

        if (success)
            ptr_->push_back(val_);

        return success;
    }

    ProgramOptionBase *clone () const
    {
        ProgramOptionBase *ptr = new ProgramOptionVector<T>(*this);

        return ptr;
    }

    private :

    T val_;
    std::vector<T> *const ptr_;
}; // class ProgramOptionVector

/// \brief A map of ProgramOption
/// \ingroup Option
///
/// \details
/// Basic example:
/// \code
/// int main (int argc, char **argv)
/// {
///     double Value1;
///     double Value2;
///     std::vector<double> Value3;
///     std::vector<double> Value4;
///     ProgramOptionMap Map;
///     Map.add<double>("option1", "option description string 1", &Value1);
///     Map.add<double>("option2", "option description string 2", &Value2);
///     Map.add<double>("option3", "option description string 3", &Value3);
///     Map.add<double>("option4", "option description string 4", &Value4, 401);
///     if (Map.process(argc, argv)) // Help info was printed
///         return 0;
///
///     std::cout << Value1 << std::endl;
///     std::cout << Value2 << std::endl;
///     for (std::size_t i = 0; i != Value3.size(); ++i)
///         std::cout << Value3[i] << std::endl;
///     for (std::size_t i = 0; i != Value4.size(); ++i)
///         std::cout << Value4[i] << std::endl;
/// }
/// \endcode
/// And if on the command line,
/// \code
/// ./prog --option1 101 --option2 201 --option2 202 --option3 301 --option3 202 --option4 402
/// \end
/// will produce the output
/// \code
/// 101
/// 202
/// 301
/// 302
/// 401
/// 402
/// \endcode
/// An option may be specified multiple times on the command line. If the
/// option's value type is a specialization of std::vector, then all values
/// will be stored. Otherwise only the last one will be stored. A default value
/// may be specified for an option. If an option's value type is a
/// specializaiton of std::vector, then values specified on the command line
/// will be appended to the destination vector instead of override the defualt
/// value.
///
/// If add an option with a name that already exists, then it overrides the
/// previous one
class ProgramOptionMap
{
    public :

    typedef std::map<std::string, std::pair<ProgramOptionBase *, std::size_t> >
        option_map_type;

    ProgramOptionMap () {}

    ProgramOptionMap (const ProgramOptionMap &other) :
        option_map_(other.option_map_)
    {
        for (option_map_type::iterator iter = option_map_.begin();
                iter != option_map_.end(); ++iter) {
            if (iter->second.first)
                iter->second.first = iter->second.first->clone();
        }
    }

    ProgramOptionMap &operator= (const ProgramOptionMap &other)
    {
        if (this != &other) {
            for (option_map_type::iterator iter = option_map_.begin();
                    iter != option_map_.end(); ++iter) {
                if (iter->second.first)
                    delete iter->second.first;
            }

            option_map_ = other.option_map_;

            for (option_map_type::iterator iter = option_map_.begin();
                    iter != option_map_.end(); ++iter) {
                if (iter->second.first)
                    iter->second.first = iter->second.first->clone();
            }
        }

        return *this;
    }

    ~ProgramOptionMap ()
    {
        for (option_map_type::iterator iter = option_map_.begin();
                iter != option_map_.end(); ++iter) {
            if (iter->second.first)
                delete iter->second.first;
        }
    }

    /// \brief Add an option with a single value
    ///
    /// \param name Name of the option, on command name it shall be specified
    /// by --name
    /// \param desc A descritpion stream of the option
    /// \param ptr The destination that store the option value
    template <typename T>
    ProgramOptionMap &add (const std::string &name, const std::string &desc,
            T *ptr)
    {
        VSMC_RUNTIME_ASSERT_UTILITY_PROGRAM_OPTION_NULLPTR(ptr, add);
        const std::string oname("--" + name);
        ProgramOptionBase *optr = new ProgramOptionScalar<T>(desc, ptr);
        add_option(oname, optr);

        return *this;
    }

    /// \brief Add an option with a single value, with a default value
    template <typename T, typename V>
    ProgramOptionMap &add (const std::string &name, const std::string &desc,
            T *ptr, const V &val)
    {
        VSMC_RUNTIME_ASSERT_UTILITY_PROGRAM_OPTION_NULLPTR(ptr, add);
        const std::string oname("--" + name);
        ProgramOptionBase *optr = new ProgramOptionScalar<T>(desc, ptr, val);
        add_option(oname, optr);

        return *this;
    }

    /// \brief Add an opiton with multiple value
    template <typename T>
    ProgramOptionMap &add (const std::string &name, const std::string &desc,
            std::vector<T> *ptr)
    {
        VSMC_RUNTIME_ASSERT_UTILITY_PROGRAM_OPTION_NULLPTR(ptr, add);
        const std::string oname("--" + name);
        ProgramOptionBase *optr = new ProgramOptionVector<T>(desc, ptr);
        add_option(oname, optr);

        return *this;
    }

    /// \brief Add an opiton with multiple value, with a default value
    template <typename T, typename V>
    ProgramOptionMap &add (const std::string &name, const std::string &desc,
            std::vector<T> *ptr, const V &val)
    {
        VSMC_RUNTIME_ASSERT_UTILITY_PROGRAM_OPTION_NULLPTR(ptr, add);
        const std::string oname("--" + name);
        ProgramOptionBase *optr = new ProgramOptionVector<T>(desc, ptr, val);
        add_option(oname, optr);

        return *this;
    }

    ProgramOptionMap &remove (const std::string &name)
    {
        option_map_type::iterator iter = option_map_.find("--" + name);
        if (iter != option_map_.end()) {
            if (iter->second.first)
                delete iter->second.first;
            option_map_.erase(iter);
        }

        return *this;
    }

    /// \brief Process the options
    ///
    /// \details
    /// If the option "--help" is given at the commad line, help information
    /// are printed.
    ///
    /// \param argc The first argument of the `main` function
    /// \param argv The second argument of the `main` function
    ///
    /// \return `true` If the option `--help` has been specified on the command
    /// line. Otherwise `false`.
    bool process (int argc, const char **argv)
    {
        std::vector<std::string> arg_vector;
        arg_vector.reserve(static_cast<std::size_t>(argc));
        for (int i = 0; i != argc; ++i)
            arg_vector.push_back(argv[i]);

        return process_option(arg_vector);
    }

    /// \brief Process the options
    bool process (int argc, char **argv)
    {
        std::vector<std::string> arg_vector;
        arg_vector.reserve(static_cast<std::size_t>(argc));
        for (int i = 0; i != argc; ++i)
            arg_vector.push_back(argv[i]);

        return process_option(arg_vector);
    }

    /// \brief Count the number of occurence of an option on the command line
    /// given its name
    std::size_t count (const std::string &name) const
    {
        option_map_type::const_iterator iter = option_map_.find("--" + name);
        if (iter != option_map_.end())
            return iter->second.second;
        else
            return 0;
    }

    private :

    option_map_type option_map_;
    mutable std::stringstream ss_;

    void add_option (const std::string &oname, ProgramOptionBase *optr)
    {
        std::pair<option_map_type::iterator, bool> set =
            option_map_.insert(std::make_pair(oname,
                        std::make_pair(optr, static_cast<std::size_t>(0))));
        if (!set.second) {
            if (set.first->second.first)
                delete set.first->second.first;
            set.first->second.first = optr;
        }
    }

    bool process_option (std::vector<std::string> &arg_vector)
    {
        bool help = false;
        const std::string oname_help("--help");
        const std::vector<std::string> empty_value;
        std::vector<std::pair<std::string, std::vector<std::string> > >
            option_vector;

        std::vector<std::string>::iterator aiter = arg_vector.begin();
        while (!is_option(*aiter) && aiter != arg_vector.end())
            ++aiter;
        while (aiter != arg_vector.end()) {
            if (*aiter == oname_help) {
                help = true;
                while (!is_option(*aiter) && aiter != arg_vector.end())
                    ++aiter;
            }
            option_vector.push_back(std::make_pair(*aiter, empty_value));
            std::vector<std::string> &value = option_vector.back().second;
            ++aiter;
            while (!is_option(*aiter) && aiter != arg_vector.end()) {
                value.push_back(*aiter);
                ++aiter;
            }
        }

        if (help) {
            for (option_map_type::iterator iter = option_map_.begin();
                    iter != option_map_.end(); ++iter) {
                iter->second.first->print_help(iter->first);
            }
        }

        for (std::vector<std::pair<std::string, std::vector<std::string> > >::
                iterator iter = option_vector.begin();
                iter != option_vector.end(); ++iter) {
            option_map_type::iterator miter = option_map_.find(iter->first);
            if (miter == option_map_.end())
                continue;
            bool proc = false;
            const std::size_t vsize = iter->second.size();
            for (std::size_t i = 0; i != vsize; ++i)
                proc = process_option(miter, iter->second[i]) || proc;
            if (proc)
                ++miter->second.second;
        }

        for (option_map_type::iterator iter = option_map_.begin();
                iter != option_map_.end(); ++iter) {
            if (iter->second.second == 0)
                if (iter->second.first->set_default())
                    iter->second.second = 1;
        }

        return help;
    }

    bool process_option (option_map_type::iterator iter, std::string &sval)
    {
        std::size_t e = sval.size();
        std::size_t n = 0;
        while (e != 0 && (sval[e] == ' ' || sval[e] == ',')) {
            ++n;
            --e;
        }
        if (n != 0)
            sval.erase(++e, n);

        if (sval.empty())
            return false;

        if (!iter->second.first->set(ss_, iter->first, sval))
            return false;

        return true;
    }

    bool is_option (const std::string &str)
    {
        if (str.size() < 3)
            return false;

        if (str[0] != '-')
            return false;

        if (str[1] != '-')
            return false;

        return true;
    }

    void process_value (std::string &str)
    {
        if (str.back() == ',')
            str.erase(--str.end());
    }
}; // class ProgramOptionMap

} // namespace vsmc

#endif // VSMC_UTILITY_PROGRAM_OPTION_HPP
<commit_msg>simplify doc<commit_after>#ifndef VSMC_UTILITY_PROGRAM_OPTION_HPP
#define VSMC_UTILITY_PROGRAM_OPTION_HPP

#include <vsmc/internal/common.hpp>

#define VSMC_RUNTIME_ASSERT_UTILITY_PROGRAM_OPTION_NULLPTR(ptr, func) \
    VSMC_RUNTIME_ASSERT((bool(ptr)),                                         \
            ("**vsmc::ProgramOptionMap::"#func                               \
             "** ATTEMPT TO SET OPTION WITH A NULL POINTER"))

namespace vsmc {

/// \brief Program option base class
/// \ingroup Option
class ProgramOptionBase
{
    public :

    ProgramOptionBase () {}
    ProgramOptionBase (const ProgramOptionBase &) {}
    ProgramOptionBase &operator= (const ProgramOptionBase &) {return *this;}

    virtual bool set (std::stringstream &, const std::string &,
            const std::string &) = 0;
    virtual bool set_default () = 0;
    virtual void print_help (const std::string &) const = 0;
    virtual ProgramOptionBase *clone () const = 0;
    virtual ~ProgramOptionBase () {}

    protected :

    template <typename T>
    bool set_value (std::stringstream &ss, const std::string &oname,
            const std::string &sval, T *dest)
    {
        ss.clear();
        ss.str(sval);
        T tval;
        ss >> tval;
        if (ss.fail()) {
            std::fprintf(stderr,
                    "Failed to set value of option '%s': %s\n",
                    oname.c_str(), sval.c_str());
            ss.clear();
            return false;
        }
#if VSMC_HAS_CXX11_RVALUE_REFERENCES
        *dest = cxx11::move(tval);
#else
        *dest = tval;
#endif

        return true;
    }
}; // class ProgramOptionBase

/// \brief Opiton with a default value
/// \ingroup Option
///
/// \details
/// Basic example
/// ~~~{.cpp}
/// #include <vsmc/utility/program_option.hpp>
///
/// int main (int argc, char **argv)
/// {
///     double Value;
///     ProgramOptionMap Map;
///     Map.add("option_name", "option description", &Value);
///     if (Map.process(argc, argv)) // Help info was printed
///         return 0;
///
///     std::cout << Value << std::endl;
/// }
/// ~~~
/// And if on the command line,
/// ~~~{.sh}
/// ./prog --option_name 0.5
/// ~~~
/// will produce the output
/// ~~~{.txt}
/// 0.5
/// ~~~
template <typename T>
class ProgramOptionDefault : public ProgramOptionBase
{
    public :

    ProgramOptionDefault (const std::string &desc) :
        desc_(desc), default_(T()), has_default_(false) {}

    template <typename V>
    ProgramOptionDefault (const std::string &desc, const V &val) :
        desc_(desc), default_(static_cast<T>(val)), has_default_(true) {}

    void print_help (const std::string &oname) const
    {
        std::cout << "  " << std::setw(20) << std::left << oname << desc_;
        if (has_default_)
            std::cout << " (default: " << default_ << ")";
        std::cout << std::endl;
    }

    protected :

    bool set_value_default (T *dest)
    {
        if (has_default_)
            *dest = default_;

        return has_default_;
    }

    private :

    std::string desc_;
    T default_;
    bool has_default_;
}; // ProgramOptionDefault

/// \brief Option with a single value
/// \ingroup Option
template <typename T>
class ProgramOptionScalar : public ProgramOptionDefault<T>
{
    public :

    ProgramOptionScalar (const std::string &desc, T *ptr) :
        ProgramOptionDefault<T>(desc), ptr_(ptr) {}

    template <typename V>
    ProgramOptionScalar (const std::string &desc, T *ptr, const V &val) :
        ProgramOptionDefault<T>(desc, val), ptr_(ptr) {}

    bool set (std::stringstream &ss, const std::string &oname,
            const std::string &sval)
    {return this->set_value(ss, oname, sval, ptr_);}

    bool set_default () {return this->set_value_default(ptr_);}

    ProgramOptionBase *clone () const
    {
        ProgramOptionBase *ptr = new ProgramOptionScalar<T>(*this);

        return ptr;
    }

    private :

    T *const ptr_;
}; // class ProgramOptionScalar

/// \brief Option with multiple values
/// \ingroup Option
template <typename T>
class ProgramOptionVector : public ProgramOptionDefault<T>
{
    public :

    ProgramOptionVector (const std::string &desc, std::vector<T> *ptr) :
        ProgramOptionDefault<T>(desc), val_(T()), ptr_(ptr) {}

    template <typename V>
    ProgramOptionVector (const std::string &desc, std::vector<T> *ptr,
            const V &val) :
        ProgramOptionDefault<T>(desc, val), val_(T()), ptr_(ptr) {}

    bool set (std::stringstream &ss, const std::string &oname,
            const std::string &sval)
    {
        bool success = this->set_value(ss, oname, sval, &val_);

        if (success)
            ptr_->push_back(val_);

        return success;
    }

    bool set_default ()
    {
        bool success = this->set_value_default(&val_);

        if (success)
            ptr_->push_back(val_);

        return success;
    }

    ProgramOptionBase *clone () const
    {
        ProgramOptionBase *ptr = new ProgramOptionVector<T>(*this);

        return ptr;
    }

    private :

    T val_;
    std::vector<T> *const ptr_;
}; // class ProgramOptionVector

/// \brief A map of ProgramOption
/// \ingroup Option
class ProgramOptionMap
{
    public :

    typedef std::map<std::string, std::pair<ProgramOptionBase *, std::size_t> >
        option_map_type;

    ProgramOptionMap () {}

    ProgramOptionMap (const ProgramOptionMap &other) :
        option_map_(other.option_map_)
    {
        for (option_map_type::iterator iter = option_map_.begin();
                iter != option_map_.end(); ++iter) {
            if (iter->second.first)
                iter->second.first = iter->second.first->clone();
        }
    }

    ProgramOptionMap &operator= (const ProgramOptionMap &other)
    {
        if (this != &other) {
            for (option_map_type::iterator iter = option_map_.begin();
                    iter != option_map_.end(); ++iter) {
                if (iter->second.first)
                    delete iter->second.first;
            }

            option_map_ = other.option_map_;

            for (option_map_type::iterator iter = option_map_.begin();
                    iter != option_map_.end(); ++iter) {
                if (iter->second.first)
                    iter->second.first = iter->second.first->clone();
            }
        }

        return *this;
    }

    ~ProgramOptionMap ()
    {
        for (option_map_type::iterator iter = option_map_.begin();
                iter != option_map_.end(); ++iter) {
            if (iter->second.first)
                delete iter->second.first;
        }
    }

    /// \brief Add an option with a single value
    ///
    /// \param name Name of the option, on command name it shall be specified
    /// by --name
    /// \param desc A descritpion stream of the option
    /// \param ptr The destination that store the option value
    template <typename T>
    ProgramOptionMap &add (const std::string &name, const std::string &desc,
            T *ptr)
    {
        VSMC_RUNTIME_ASSERT_UTILITY_PROGRAM_OPTION_NULLPTR(ptr, add);
        const std::string oname("--" + name);
        ProgramOptionBase *optr = new ProgramOptionScalar<T>(desc, ptr);
        add_option(oname, optr);

        return *this;
    }

    /// \brief Add an option with a single value, with a default value
    template <typename T, typename V>
    ProgramOptionMap &add (const std::string &name, const std::string &desc,
            T *ptr, const V &val)
    {
        VSMC_RUNTIME_ASSERT_UTILITY_PROGRAM_OPTION_NULLPTR(ptr, add);
        const std::string oname("--" + name);
        ProgramOptionBase *optr = new ProgramOptionScalar<T>(desc, ptr, val);
        add_option(oname, optr);

        return *this;
    }

    /// \brief Add an opiton with multiple value
    template <typename T>
    ProgramOptionMap &add (const std::string &name, const std::string &desc,
            std::vector<T> *ptr)
    {
        VSMC_RUNTIME_ASSERT_UTILITY_PROGRAM_OPTION_NULLPTR(ptr, add);
        const std::string oname("--" + name);
        ProgramOptionBase *optr = new ProgramOptionVector<T>(desc, ptr);
        add_option(oname, optr);

        return *this;
    }

    /// \brief Add an opiton with multiple value, with a default value
    template <typename T, typename V>
    ProgramOptionMap &add (const std::string &name, const std::string &desc,
            std::vector<T> *ptr, const V &val)
    {
        VSMC_RUNTIME_ASSERT_UTILITY_PROGRAM_OPTION_NULLPTR(ptr, add);
        const std::string oname("--" + name);
        ProgramOptionBase *optr = new ProgramOptionVector<T>(desc, ptr, val);
        add_option(oname, optr);

        return *this;
    }

    ProgramOptionMap &remove (const std::string &name)
    {
        option_map_type::iterator iter = option_map_.find("--" + name);
        if (iter != option_map_.end()) {
            if (iter->second.first)
                delete iter->second.first;
            option_map_.erase(iter);
        }

        return *this;
    }

    /// \brief Process the options
    ///
    /// \details
    /// If the option "--help" is given at the commad line, help information
    /// are printed.
    ///
    /// \param argc The first argument of the `main` function
    /// \param argv The second argument of the `main` function
    ///
    /// \return `true` If the option `--help` has been specified on the command
    /// line. Otherwise `false`.
    bool process (int argc, const char **argv)
    {
        std::vector<std::string> arg_vector;
        arg_vector.reserve(static_cast<std::size_t>(argc));
        for (int i = 0; i != argc; ++i)
            arg_vector.push_back(argv[i]);

        return process_option(arg_vector);
    }

    /// \brief Process the options
    bool process (int argc, char **argv)
    {
        std::vector<std::string> arg_vector;
        arg_vector.reserve(static_cast<std::size_t>(argc));
        for (int i = 0; i != argc; ++i)
            arg_vector.push_back(argv[i]);

        return process_option(arg_vector);
    }

    /// \brief Count the number of occurence of an option on the command line
    /// given its name
    std::size_t count (const std::string &name) const
    {
        option_map_type::const_iterator iter = option_map_.find("--" + name);
        if (iter != option_map_.end())
            return iter->second.second;
        else
            return 0;
    }

    private :

    option_map_type option_map_;
    mutable std::stringstream ss_;

    void add_option (const std::string &oname, ProgramOptionBase *optr)
    {
        std::pair<option_map_type::iterator, bool> set =
            option_map_.insert(std::make_pair(oname,
                        std::make_pair(optr, static_cast<std::size_t>(0))));
        if (!set.second) {
            if (set.first->second.first)
                delete set.first->second.first;
            set.first->second.first = optr;
        }
    }

    bool process_option (std::vector<std::string> &arg_vector)
    {
        bool help = false;
        const std::string oname_help("--help");
        const std::vector<std::string> empty_value;
        std::vector<std::pair<std::string, std::vector<std::string> > >
            option_vector;

        std::vector<std::string>::iterator aiter = arg_vector.begin();
        while (!is_option(*aiter) && aiter != arg_vector.end())
            ++aiter;
        while (aiter != arg_vector.end()) {
            if (*aiter == oname_help) {
                help = true;
                while (!is_option(*aiter) && aiter != arg_vector.end())
                    ++aiter;
            }
            option_vector.push_back(std::make_pair(*aiter, empty_value));
            std::vector<std::string> &value = option_vector.back().second;
            ++aiter;
            while (!is_option(*aiter) && aiter != arg_vector.end()) {
                value.push_back(*aiter);
                ++aiter;
            }
        }

        if (help) {
            for (option_map_type::iterator iter = option_map_.begin();
                    iter != option_map_.end(); ++iter) {
                iter->second.first->print_help(iter->first);
            }
        }

        for (std::vector<std::pair<std::string, std::vector<std::string> > >::
                iterator iter = option_vector.begin();
                iter != option_vector.end(); ++iter) {
            option_map_type::iterator miter = option_map_.find(iter->first);
            if (miter == option_map_.end())
                continue;
            bool proc = false;
            const std::size_t vsize = iter->second.size();
            for (std::size_t i = 0; i != vsize; ++i)
                proc = process_option(miter, iter->second[i]) || proc;
            if (proc)
                ++miter->second.second;
        }

        for (option_map_type::iterator iter = option_map_.begin();
                iter != option_map_.end(); ++iter) {
            if (iter->second.second == 0)
                if (iter->second.first->set_default())
                    iter->second.second = 1;
        }

        return help;
    }

    bool process_option (option_map_type::iterator iter, std::string &sval)
    {
        std::size_t e = sval.size();
        std::size_t n = 0;
        while (e != 0 && (sval[e] == ' ' || sval[e] == ',')) {
            ++n;
            --e;
        }
        if (n != 0)
            sval.erase(++e, n);

        if (sval.empty())
            return false;

        if (!iter->second.first->set(ss_, iter->first, sval))
            return false;

        return true;
    }

    bool is_option (const std::string &str)
    {
        if (str.size() < 3)
            return false;

        if (str[0] != '-')
            return false;

        if (str[1] != '-')
            return false;

        return true;
    }

    void process_value (std::string &str)
    {
        if (str.back() == ',')
            str.erase(--str.end());
    }
}; // class ProgramOptionMap

} // namespace vsmc

#endif // VSMC_UTILITY_PROGRAM_OPTION_HPP
<|endoftext|>


<commit_before>/*=========================================================================
 *
 *  Copyright 2011-2013 The University of North Carolina at Chapel Hill
 *  All rights reserved.
 *
 *  Licensed under the MADAI Software License. You may obtain a copy of
 *  this license at
 *
 *         https://madai-public.cs.unc.edu/visualization/software-license/
 *
 *  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 <cassert>  // assert
#include <cstdlib>  // std::atof
#include <cmath>    // std::sqrt, std::pow
#include <iomanip>  // std::setw
#include <iostream> // std::cout
#include <fstream>  // std::ifstream
#include <limits>   // infinity
#include <sstream>  // std::stringstream
#include <string>   // std::string
#include <vector>   // std::vector

#include "ApplicationUtilities.h"
#include "Defaults.h"
#include "GaussianProcessEmulatorDirectoryFormatIO.h"
#include "Paths.h"
#include "RuntimeParameterFileReader.h"
#include "System.h"

#include "madaisys/SystemTools.hxx"

int main(int argc, char ** argv) {

  if (argc < 4) {
    std::cerr
      << "Usage\n  " << argv[0]
      << " <statistics directory> <trace file> <number of samples>\n"
      << "\n"
      << "This program samples a trace file located at <trace file>.\n"
      << "The argument <number of samples> specifies how many \n"
      << "samples are taken from the trace. Each sample is stored in a\n"
      << "directory specified by the setting POSTERIOR_ANALYSIS_DIRECTORY in \n"
      << "the same format as the model output generated by \n"
      << "madai_generate_training_points. In addition, a file named\n"
      << "'trace_results.dat' is stored in each run directory. This file \n"
      << "contains the observables listed in the trace.\n"
      << "\n"
      << "The output of this program can be used to generate results from the \n"
      << "actual model to compare against the output from the emulator. If \n"
      << "your original trace is from an actual model, then use of this \n"
      << "program is not necessarily useful.\n"
      << "\n"
      << "Format of entries in " << madai::Paths::RUNTIME_PARAMETER_FILE
      << ":\n\n"
      << "POSTERIOR_ANALYSIS_DIRECTORY <value> (default: "
      << madai::Defaults::POSTERIOR_ANALYSIS_DIRECTORY << ")\n"
      << "VERBOSE <value> (default: "
      << madai::Defaults::VERBOSE << ")\n";

    return EXIT_FAILURE;
  }

  std::string statisticsDirectory( argv[1] );
  madai::EnsurePathSeparatorAtEnd( statisticsDirectory );

  madai::RuntimeParameterFileReader settings;
  std::string settingsFile = statisticsDirectory + madai::Paths::RUNTIME_PARAMETER_FILE;
  if ( !settings.ParseFile( settingsFile ) ) {
    std::cerr << "Could not open runtime parameter file '" << settingsFile << "'\n";
    return EXIT_FAILURE;
  }

  std::vector< madai::Parameter > parameters;
  int numberOfParameters = 0;

  if ( ! madai::GaussianProcessEmulatorDirectoryFormatIO::ParseParameters(
           parameters, numberOfParameters, statisticsDirectory, false )) {
    std::cerr
      << "Could not read parameters from prior file '"
      << statisticsDirectory << madai::Paths::PARAMETER_PRIORS_FILE << "'\n";
    return EXIT_FAILURE;
  }
  assert ( numberOfParameters == static_cast<int>( parameters.size() ) );

  std::vector< std::string > observableNames;
  int numberOfObservables = 0;
  if ( ! madai::GaussianProcessEmulatorDirectoryFormatIO::ParseOutputs(
           observableNames, numberOfObservables, statisticsDirectory, false ) ) {
    std::cerr
      << "Could not read observable names from file '"
      << statisticsDirectory << madai::Paths::OBSERVABLE_NAMES_FILE << "'\n";
    return EXIT_FAILURE;
  }
  assert( numberOfObservables == static_cast<int>( observableNames.size() ) );

  std::string traceFile( argv[2] );
  int numberOfPosteriorSamples = atoi(argv[3]);

  if ( !madai::System::IsFile( traceFile ) ) {
    std::cerr << "Trace file '" << traceFile << "' does not exist or is a directory.\n";
    return EXIT_FAILURE;
  }

  std::ifstream trace( traceFile.c_str() );
  if ( !trace.good() ) {
    std::cerr << "Error reading trace file '" << traceFile << "'.\n";
    return EXIT_FAILURE;
  }

  std::string header;
  std::getline( trace, header );
  std::vector<std::string> headers = madai::SplitString( header, ',' );

  // Drop the quotes from around the file names
  for ( size_t i = 0; i < headers.size(); ++i ) {
    size_t firstQuote = headers[i].find_first_of( '"' );
    if ( firstQuote != std::string::npos ) {
      size_t secondQuote = headers[i].find_last_of( '"');
      if ( secondQuote != std::string::npos ) {
        headers[i] = headers[i].substr( firstQuote+1, (secondQuote-firstQuote-1) );
      }
    }
  }

  assert(static_cast<int>(headers.size())
         == numberOfParameters + numberOfObservables + 1);

  std::string line;
  size_t lineCount = 0;
  std::vector< std::vector< double > > values(numberOfParameters);
  std::vector< std::vector< double > > observables(numberOfObservables);

  while ( std::getline( trace, line ) ) {
    std::vector<std::string> fields = madai::SplitString( line, ',' );
    assert( headers.size() == fields.size() );

    for ( int i = 0; i < numberOfParameters; ++i ) {
      double value = std::atof( fields[i].c_str() );
      values[i].push_back( value );
    }

    for ( int i = 0; i < numberOfObservables; ++i ) {
      double value = std::atof( fields[i + numberOfParameters].c_str() );
      observables[i].push_back( value );
    }

    ++lineCount;
  }
  trace.close();

  // Make the requested directory
  std::string posteriorAnalysisDirectory =
    madai::GetPosteriorAnalysisDirectory( statisticsDirectory, settings );
  if ( !madaisys::SystemTools::MakeDirectory( posteriorAnalysisDirectory.c_str() ) ) {
    std::cerr << "Could not create posterior analysis directory '"
              << posteriorAnalysisDirectory << "'.\n";
    return EXIT_FAILURE;
  }

  assert( numberOfPosteriorSamples <= int(lineCount) );
  for ( int isample = 0; isample < numberOfPosteriorSamples; isample++ ) {
    // Make the posterior sample model output directory
    std::stringstream ssRunDirectory;
    ssRunDirectory << posteriorAnalysisDirectory
                   << madai::Paths::SEPARATOR << "run" << std::setw(4)
                   << std::setfill('0') << isample
                   << madai::Paths::SEPARATOR;
    std::string runDirectory( ssRunDirectory.str() );
    bool directoryCreated = madaisys::SystemTools::MakeDirectory( runDirectory.c_str() );
    if ( !directoryCreated ) {
      std::cerr << "Could not create directory '" << posteriorAnalysisDirectory
                << "'.\n";
      return EXIT_FAILURE;
    }

    unsigned int iline = lrint(-1+(isample+1)*lineCount /
                               numberOfPosteriorSamples);
    assert(iline < lineCount);

    // Write parameters
    std::string parameterFileName =
      runDirectory + madai::Paths::SEPARATOR + "parameters.dat";
    std::ofstream parameterFile( parameterFileName.c_str() );
    if ( !parameterFile.is_open() ) {
      std::cerr << "Could not open parameter file '" << parameterFileName << "'.\n";
      return EXIT_FAILURE;
    }

    for ( int i = 0; i < numberOfParameters; i++ ) {
      parameterFile << headers[i] << " " << values[i][iline] << "\n";
    }
    parameterFile.close();

    // Write observables
    std::string observablesFileName =
      runDirectory + madai::Paths::SEPARATOR + "trace_results.dat";
    std::ofstream observablesFile( observablesFileName.c_str() );
    if ( !observablesFile.is_open() ) {
      std::cerr << "Could not open outputs file '" << observablesFileName << "'.\n";
      return EXIT_FAILURE;
    }

    for ( int i = 0; i < numberOfObservables; ++i ) {
      observablesFile << headers[numberOfParameters + i] << " "
                  << observables[i][iline] << "\n";
    }
    observablesFile.close();
  }

  return EXIT_SUCCESS;
}
<commit_msg>Added definition of lrint() for Visual Studio<commit_after>/*=========================================================================
 *
 *  Copyright 2011-2013 The University of North Carolina at Chapel Hill
 *  All rights reserved.
 *
 *  Licensed under the MADAI Software License. You may obtain a copy of
 *  this license at
 *
 *         https://madai-public.cs.unc.edu/visualization/software-license/
 *
 *  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 <cassert>  // assert
#include <cstdlib>  // std::atof
#include <cmath>    // std::sqrt, std::pow
#include <iomanip>  // std::setw
#include <iostream> // std::cout
#include <fstream>  // std::ifstream
#include <limits>   // infinity
#include <sstream>  // std::stringstream
#include <string>   // std::string
#include <vector>   // std::vector

#include "ApplicationUtilities.h"
#include "Defaults.h"
#include "GaussianProcessEmulatorDirectoryFormatIO.h"
#include "Paths.h"
#include "RuntimeParameterFileReader.h"
#include "System.h"

#include "madaisys/SystemTools.hxx"

#ifdef WIN32
#define lrint(x) (floor(x+(x>0) ? 0.5 : -0.5))
#endif

int main(int argc, char ** argv) {

  if (argc < 4) {
    std::cerr
      << "Usage\n  " << argv[0]
      << " <statistics directory> <trace file> <number of samples>\n"
      << "\n"
      << "This program samples a trace file located at <trace file>.\n"
      << "The argument <number of samples> specifies how many \n"
      << "samples are taken from the trace. Each sample is stored in a\n"
      << "directory specified by the setting POSTERIOR_ANALYSIS_DIRECTORY in \n"
      << "the same format as the model output generated by \n"
      << "madai_generate_training_points. In addition, a file named\n"
      << "'trace_results.dat' is stored in each run directory. This file \n"
      << "contains the observables listed in the trace.\n"
      << "\n"
      << "The output of this program can be used to generate results from the \n"
      << "actual model to compare against the output from the emulator. If \n"
      << "your original trace is from an actual model, then use of this \n"
      << "program is not necessarily useful.\n"
      << "\n"
      << "Format of entries in " << madai::Paths::RUNTIME_PARAMETER_FILE
      << ":\n\n"
      << "POSTERIOR_ANALYSIS_DIRECTORY <value> (default: "
      << madai::Defaults::POSTERIOR_ANALYSIS_DIRECTORY << ")\n"
      << "VERBOSE <value> (default: "
      << madai::Defaults::VERBOSE << ")\n";

    return EXIT_FAILURE;
  }

  std::string statisticsDirectory( argv[1] );
  madai::EnsurePathSeparatorAtEnd( statisticsDirectory );

  madai::RuntimeParameterFileReader settings;
  std::string settingsFile = statisticsDirectory + madai::Paths::RUNTIME_PARAMETER_FILE;
  if ( !settings.ParseFile( settingsFile ) ) {
    std::cerr << "Could not open runtime parameter file '" << settingsFile << "'\n";
    return EXIT_FAILURE;
  }

  std::vector< madai::Parameter > parameters;
  int numberOfParameters = 0;

  if ( ! madai::GaussianProcessEmulatorDirectoryFormatIO::ParseParameters(
           parameters, numberOfParameters, statisticsDirectory, false )) {
    std::cerr
      << "Could not read parameters from prior file '"
      << statisticsDirectory << madai::Paths::PARAMETER_PRIORS_FILE << "'\n";
    return EXIT_FAILURE;
  }
  assert ( numberOfParameters == static_cast<int>( parameters.size() ) );

  std::vector< std::string > observableNames;
  int numberOfObservables = 0;
  if ( ! madai::GaussianProcessEmulatorDirectoryFormatIO::ParseOutputs(
           observableNames, numberOfObservables, statisticsDirectory, false ) ) {
    std::cerr
      << "Could not read observable names from file '"
      << statisticsDirectory << madai::Paths::OBSERVABLE_NAMES_FILE << "'\n";
    return EXIT_FAILURE;
  }
  assert( numberOfObservables == static_cast<int>( observableNames.size() ) );

  std::string traceFile( argv[2] );
  int numberOfPosteriorSamples = atoi(argv[3]);

  if ( !madai::System::IsFile( traceFile ) ) {
    std::cerr << "Trace file '" << traceFile << "' does not exist or is a directory.\n";
    return EXIT_FAILURE;
  }

  std::ifstream trace( traceFile.c_str() );
  if ( !trace.good() ) {
    std::cerr << "Error reading trace file '" << traceFile << "'.\n";
    return EXIT_FAILURE;
  }

  std::string header;
  std::getline( trace, header );
  std::vector<std::string> headers = madai::SplitString( header, ',' );

  // Drop the quotes from around the file names
  for ( size_t i = 0; i < headers.size(); ++i ) {
    size_t firstQuote = headers[i].find_first_of( '"' );
    if ( firstQuote != std::string::npos ) {
      size_t secondQuote = headers[i].find_last_of( '"');
      if ( secondQuote != std::string::npos ) {
        headers[i] = headers[i].substr( firstQuote+1, (secondQuote-firstQuote-1) );
      }
    }
  }

  assert(static_cast<int>(headers.size())
         == numberOfParameters + numberOfObservables + 1);

  std::string line;
  size_t lineCount = 0;
  std::vector< std::vector< double > > values(numberOfParameters);
  std::vector< std::vector< double > > observables(numberOfObservables);

  while ( std::getline( trace, line ) ) {
    std::vector<std::string> fields = madai::SplitString( line, ',' );
    assert( headers.size() == fields.size() );

    for ( int i = 0; i < numberOfParameters; ++i ) {
      double value = std::atof( fields[i].c_str() );
      values[i].push_back( value );
    }

    for ( int i = 0; i < numberOfObservables; ++i ) {
      double value = std::atof( fields[i + numberOfParameters].c_str() );
      observables[i].push_back( value );
    }

    ++lineCount;
  }
  trace.close();

  // Make the requested directory
  std::string posteriorAnalysisDirectory =
    madai::GetPosteriorAnalysisDirectory( statisticsDirectory, settings );
  if ( !madaisys::SystemTools::MakeDirectory( posteriorAnalysisDirectory.c_str() ) ) {
    std::cerr << "Could not create posterior analysis directory '"
              << posteriorAnalysisDirectory << "'.\n";
    return EXIT_FAILURE;
  }

  assert( numberOfPosteriorSamples <= int(lineCount) );
  for ( int isample = 0; isample < numberOfPosteriorSamples; isample++ ) {
    // Make the posterior sample model output directory
    std::stringstream ssRunDirectory;
    ssRunDirectory << posteriorAnalysisDirectory
                   << madai::Paths::SEPARATOR << "run" << std::setw(4)
                   << std::setfill('0') << isample
                   << madai::Paths::SEPARATOR;
    std::string runDirectory( ssRunDirectory.str() );
    bool directoryCreated = madaisys::SystemTools::MakeDirectory( runDirectory.c_str() );
    if ( !directoryCreated ) {
      std::cerr << "Could not create directory '" << posteriorAnalysisDirectory
                << "'.\n";
      return EXIT_FAILURE;
    }

    unsigned int iline = lrint(-1+(isample+1)*lineCount /
                               numberOfPosteriorSamples);
    assert(iline < lineCount);

    // Write parameters
    std::string parameterFileName =
      runDirectory + madai::Paths::SEPARATOR + "parameters.dat";
    std::ofstream parameterFile( parameterFileName.c_str() );
    if ( !parameterFile.is_open() ) {
      std::cerr << "Could not open parameter file '" << parameterFileName << "'.\n";
      return EXIT_FAILURE;
    }

    for ( int i = 0; i < numberOfParameters; i++ ) {
      parameterFile << headers[i] << " " << values[i][iline] << "\n";
    }
    parameterFile.close();

    // Write observables
    std::string observablesFileName =
      runDirectory + madai::Paths::SEPARATOR + "trace_results.dat";
    std::ofstream observablesFile( observablesFileName.c_str() );
    if ( !observablesFile.is_open() ) {
      std::cerr << "Could not open outputs file '" << observablesFileName << "'.\n";
      return EXIT_FAILURE;
    }

    for ( int i = 0; i < numberOfObservables; ++i ) {
      observablesFile << headers[numberOfParameters + i] << " "
                  << observables[i][iline] << "\n";
    }
    observablesFile.close();
  }

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include "panel_obj.h"

using namespace std;

namespace curses {
	// Uses the userptr supplied by the panel library to store a reference
	// to the wrapper class.

	Panel::Panel(WINDOW* win) :
		Window(win),
		pan(new_panel(win), del_panel) {
		set_panel_userptr(pan.get(), this);
	}

	Panel::Panel(const int nlines, const int ncols, const int begin_y, const int begin_x) :
		Window(nlines, ncols, begin_y, begin_x),
		pan(new_panel(this->win.get()), del_panel) {
		set_panel_userptr(pan.get(), this);
	}

	const Panel& Panel::above() const {
		return *(static_cast<const Panel*>(panel_userptr(panel_above(pan.get()))));
	}

	const Panel& Panel::below() const {
		return *(static_cast<const Panel*>(panel_userptr(panel_below(pan.get()))));
	}

	void Panel::movepanel(const int start_y, const int start_x) {
		if (move_panel(pan.get(), start_y, start_x) == ERR)
			throw CursesException();
	}

	void Panel::top() {
		if (top_panel(pan.get()) == ERR)
			throw CursesException();
	}

	void Panel::bottom() {
		if (bottom_panel(pan.get()) == ERR)
			throw CursesException();
	}

	void Panel::hide() {
		if (hide_panel(pan.get()) == ERR)
			throw CursesException();
	}

	void Panel::show() {
		if (show_panel(pan.get()) == ERR)
			throw CursesException();
	}

	bool Panel::hidden() const {
		if (panel_hidden(pan.get()) == OK)
			return true;
		return false;
	}

	void Panel::update() {
		update_panels();
	}

	const Panel& Panel::topmost() {
		return *(static_cast<const Panel*>(panel_userptr(panel_above(nullptr))));
	}

	const Panel& Panel::bottommost() {
		return *(static_cast<const Panel*>(panel_userptr(panel_below(nullptr))));
	}
}<commit_msg>Fixed issue of different curses implementations behavior: PDCurses causes screen update on Panel::update() (update_panels()), whereas ncurses does not.  Since an update is desirable here, calling Panel::update() will now call doupdate() on non-PDCurses implementations. This fixes the menus on linux.<commit_after>#include "panel_obj.h"

using namespace std;

namespace curses {
	// Uses the userptr supplied by the panel library to store a reference
	// to the wrapper class.

	Panel::Panel(WINDOW* win) :
		Window(win),
		pan(new_panel(win), del_panel) {
		set_panel_userptr(pan.get(), this);
	}

	Panel::Panel(const int nlines, const int ncols, const int begin_y, const int begin_x) :
		Window(nlines, ncols, begin_y, begin_x),
		pan(new_panel(this->win.get()), del_panel) {
		set_panel_userptr(pan.get(), this);
	}

	const Panel& Panel::above() const {
		return *(static_cast<const Panel*>(panel_userptr(panel_above(pan.get()))));
	}

	const Panel& Panel::below() const {
		return *(static_cast<const Panel*>(panel_userptr(panel_below(pan.get()))));
	}

	void Panel::movepanel(const int start_y, const int start_x) {
		if (move_panel(pan.get(), start_y, start_x) == ERR)
			throw CursesException();
	}

	void Panel::top() {
		if (top_panel(pan.get()) == ERR)
			throw CursesException();
	}

	void Panel::bottom() {
		if (bottom_panel(pan.get()) == ERR)
			throw CursesException();
	}

	void Panel::hide() {
		if (hide_panel(pan.get()) == ERR)
			throw CursesException();
	}

	void Panel::show() {
		if (show_panel(pan.get()) == ERR)
			throw CursesException();
	}

	bool Panel::hidden() const {
		if (panel_hidden(pan.get()) == OK)
			return true;
		return false;
	}

	void Panel::update() {
		update_panels();
		// PDCurses causes a screen update here (which is generally desirable), so
		// for portability do the same for other curses implementations.
#ifndef PDC_BUILD
		doupdate();
#endif
	}

	const Panel& Panel::topmost() {
		return *(static_cast<const Panel*>(panel_userptr(panel_above(nullptr))));
	}

	const Panel& Panel::bottommost() {
		return *(static_cast<const Panel*>(panel_userptr(panel_below(nullptr))));
	}
}<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: svtuno.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: fs $ $Date: 2001-09-18 14:45:44 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  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., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _SVTOOLS_SVTUNO_HXX
#define _SVTOOLS_SVTUNO_HXX

// Macro to define const unicode a'la "..."
// It's better then "OUString::createFromAscii(...)" !!!
#define DEFINE_CONST_UNICODE(CONSTASCII)        UniString(RTL_CONSTASCII_USTRINGPARAM(CONSTASCII))
#define DEFINE_CONST_OUSTRING(CONSTASCII)       OUString(RTL_CONSTASCII_USTRINGPARAM(CONSTASCII))

// defines ---------------------------------------------------------------
#define UNOANY                          ::com::sun::star::uno::Any
#define UNOEXCEPTION                    ::com::sun::star::uno::Exception
#define UNOMUTEX                        ::osl::Mutex
#define UNOMUTEXGUARD                   ::osl::MutexGuard
#define UNOOIMPLEMENTATIONID            ::cppu::OImplementationId
#define UNOOTYPECOLLECTION              ::cppu::OTypeCollection
#define UNOOUSTRING                     ::rtl::OUString
#define UNOPROPERTYVALUE                ::com::sun::star::beans::PropertyValue
#define UNOSTRINGPAIR                   ::com::sun::star::beans::StringPair
#define UNOREFERENCE                    ::com::sun::star::uno::Reference
#define UNORUNTIMEEXCEPTION             ::com::sun::star::uno::RuntimeException
#define UNOINVALIDREGISTRYEXCEPTION     ::com::sun::star::registry::InvalidRegistryException
#define UNOSEQUENCE                     ::com::sun::star::uno::Sequence
#define UNOTYPE                         ::com::sun::star::uno::Type
#define UNOURL                          ::com::sun::star::util::URL
#define UNOXINTERFACE                   ::com::sun::star::uno::XInterface
#define UNOXMULTISERVICEFACTORY         ::com::sun::star::lang::XMultiServiceFactory
#define UNOXSINGLESERVICEFACTORY        ::com::sun::star::lang::XSingleServiceFactory
#define UNOXTYPEPROVIDER                ::com::sun::star::lang::XTypeProvider
#define UNOILLEGALARGUMENTEXCEPTION     ::com::sun::star::lang::IllegalArgumentException

// -----------------------------------------------------------------------

#endif
<commit_msg>INTEGRATION: CWS ooo19126 (1.2.1088); FILE MERGED 2005/09/05 14:51:11 rt 1.2.1088.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: svtuno.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 14:05:27 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _SVTOOLS_SVTUNO_HXX
#define _SVTOOLS_SVTUNO_HXX

// Macro to define const unicode a'la "..."
// It's better then "OUString::createFromAscii(...)" !!!
#define DEFINE_CONST_UNICODE(CONSTASCII)        UniString(RTL_CONSTASCII_USTRINGPARAM(CONSTASCII))
#define DEFINE_CONST_OUSTRING(CONSTASCII)       OUString(RTL_CONSTASCII_USTRINGPARAM(CONSTASCII))

// defines ---------------------------------------------------------------
#define UNOANY                          ::com::sun::star::uno::Any
#define UNOEXCEPTION                    ::com::sun::star::uno::Exception
#define UNOMUTEX                        ::osl::Mutex
#define UNOMUTEXGUARD                   ::osl::MutexGuard
#define UNOOIMPLEMENTATIONID            ::cppu::OImplementationId
#define UNOOTYPECOLLECTION              ::cppu::OTypeCollection
#define UNOOUSTRING                     ::rtl::OUString
#define UNOPROPERTYVALUE                ::com::sun::star::beans::PropertyValue
#define UNOSTRINGPAIR                   ::com::sun::star::beans::StringPair
#define UNOREFERENCE                    ::com::sun::star::uno::Reference
#define UNORUNTIMEEXCEPTION             ::com::sun::star::uno::RuntimeException
#define UNOINVALIDREGISTRYEXCEPTION     ::com::sun::star::registry::InvalidRegistryException
#define UNOSEQUENCE                     ::com::sun::star::uno::Sequence
#define UNOTYPE                         ::com::sun::star::uno::Type
#define UNOURL                          ::com::sun::star::util::URL
#define UNOXINTERFACE                   ::com::sun::star::uno::XInterface
#define UNOXMULTISERVICEFACTORY         ::com::sun::star::lang::XMultiServiceFactory
#define UNOXSINGLESERVICEFACTORY        ::com::sun::star::lang::XSingleServiceFactory
#define UNOXTYPEPROVIDER                ::com::sun::star::lang::XTypeProvider
#define UNOILLEGALARGUMENTEXCEPTION     ::com::sun::star::lang::IllegalArgumentException

// -----------------------------------------------------------------------

#endif
<|endoftext|>