////////////////////////////////////////////////////////////////////////////////
#include "Mesh.h"
#include <cellogram/State.h>
#include <cellogram/delaunay.h>
#include <cellogram/load_points.h>
#include <cellogram/convex_hull.h>
#include <cellogram/delaunay.h>
#include <cellogram/tri2hex.h>
#include <cellogram/voronoi.h>
#include <cellogram/vertex_degree.h>
#include <cellogram/laplace_energy.h>
#include <points_untangler/points_untangler.h>
#include <igl/list_to_matrix.h>
#include <igl/bounding_box.h>
#include <igl/opengl/glfw/Viewer.h>
#include <Eigen/Sparse>
#include <fstream>
////////////////////////////////////////////////////////////////////////////////

namespace cellogram {

	namespace
	{
		template<typename T>
		void removeRow(T& matrix, unsigned int rowToRemove)
		{
			unsigned int numRows = matrix.rows() - 1;
			unsigned int numCols = matrix.cols();

			if (rowToRemove < numRows)
				matrix.block(rowToRemove, 0, numRows - rowToRemove, numCols) = matrix.bottomRows(numRows - rowToRemove);

			matrix.conservativeResize(numRows, numCols);
		}

		void replaceTriangles(const Eigen::MatrixXi tNew, const Eigen::MatrixXi &to_remove, Eigen::MatrixXi &triangles)
		{
			std::vector<int> removeIdx(to_remove.data(), to_remove.data() + to_remove.rows() * to_remove.cols());
			std::sort(removeIdx.begin(), removeIdx.end());
			// remove all the triangles that connect to the internal of ROI
			for (int i = removeIdx.size() - 1; i >= 0; i--)
			{
				removeRow(triangles, removeIdx[i]);
			}

			//std::cout << tNew << "\n\n" << std::endl;

			// add new rows at the end of triangles
			Eigen::MatrixXi tmp = triangles;
			triangles.resize(triangles.rows() + tNew.rows(), triangles.cols());

			triangles << tmp, tNew;
		}

		template<typename Matrix>
		bool load_data(const std::string & path, Matrix & data_matrix)
		{
			typedef typename Matrix::Scalar Scalar;
			std::fstream file;
			file.open(path);

			if (!file.good())
			{
				std::cerr << "Failed to open file : " << path << std::endl;
				file.close();
				return false;
			}

			std::string s;
			std::vector<std::vector<Scalar>> matrix;

			while (getline(file, s))
			{
				std::stringstream input(s);
				double temp;
				matrix.emplace_back();

				auto &currentLine = matrix.back();

				while (input >> temp)
					currentLine.push_back(temp);
			}

			if (!igl::list_to_matrix(matrix, data_matrix))
			{
				std::cerr << "list to matrix error" << std::endl;
				file.close();
				return false;
			}

			return true;
		}
	}

	bool Mesh::load(const nlohmann::json &data)
	{
		params = {};
		detected.resize(0, 0); // detected (unmoved) point positions
		moved.resize(0, 0); // manually moved
		points.resize(0, 0); // relaxed point positions
		triangles.resize(0, 0); // triangular mesh
		adj.clear(); // adjaceny list of triangluar mesh
		vertex_to_tri.clear();
		boundary.resize(0); // list of vertices on the boundary
		vertex_status_fixed.resize(0);

		read_json_mat(data["detected"], detected);
		read_json_mat(data["points"], points);
		read_json_mat(data["moved"], moved);
		read_json_mat(data["triangles"], triangles);

		params.load(data["params"]);

		solved_vertex.resize(points.rows(), 1);
		solved_vertex.setConstant(false);

		adjacency_list(triangles, adj);
		generate_vertex_to_tri();

		vertex_status_fixed.resize(points.rows(), 1);
		vertex_status_fixed.setZero();

		return true;
	}

	// bool Mesh::load(const std::string & path)
	// {
	// 	if (path.empty()) { return false; }
	// 	// clear previous
	// 	params = {};
	// 	detected.resize(0, 0); // detected (unmoved) point positions
	// 	moved.resize(0, 0); // manually moved
	// 	points.resize(0, 0); // relaxed point positions
	// 	triangles.resize(0, 0); // triangular mesh
	// 	adj.clear(); // adjaceny list of triangluar mesh
	// 	vertex_to_tri.clear();
	// 	boundary.resize(0); // list of vertices on the boundary
	// 	vertex_status_fixed.resize(0);

	// 	// Load data
	// 	load_data(path + "/cellogram/detected.vert", detected);
	// 	load_data(path + "/cellogram/points.vert", points);
	// 	load_data(path + "/cellogram/moved.vert", moved);
	// 	load_data(path + "/cellogram/mesh.tri", triangles);

	// 	// change when moved is also saved
	// 	//moved = detected;

	// 	params.load(path + "/cellogram/params.json");

	// 	solved_vertex.resize(points.rows(), 1);
	// 	solved_vertex.setConstant(false);

	// 	adjacency_list(triangles, adj);
	// 	generate_vertex_to_tri();

	// 	vertex_status_fixed.resize(points.rows(), 1);
	// 	vertex_status_fixed.setZero();

	// 	return true;
	// }

	void Mesh::relax_with_lloyd(const int lloyd_iterations, const Eigen::MatrixXd &hull_vertices,const Eigen::MatrixXi &hull_faces, const bool fix_regular_regions)
	{
		//reset the state
		//points = detected;
		points = moved;
		compute_triangulation();

		Eigen::VectorXi fixed_V;
		if (fix_regular_regions)
		{
			Eigen::VectorXd energy;
			laplace_energy(moved, triangles, energy);
			// Determine whether each vertex passes the criterium for bad mesh
			double avg = energy.mean();

			// Find the degree of each vertex
			Eigen::VectorXi degree;
			vertex_degree(degree);

			Eigen::Matrix<bool, 1, Eigen::Dynamic> low_energy(moved.rows());
			low_energy.setConstant(false);
			int count = 0;
			for (int i = 0; i < moved.rows(); i++)
			{
				if (energy(i) < 0.6*avg && degree(i) == 6)
				{
					low_energy(i) = true;
					count++;
				}
			}
			for (int i = 0; i < boundary.size(); i++)
			{
				low_energy(boundary(i)) = true;
				count++;
			}
			fixed_V.resize(low_energy.size());
			count = 0;
			for (int i = 0; i < low_energy.size(); i++)
			{
				if (low_energy(i))
				{
					fixed_V(count) = i;
					count++;
				}
				//check if the vertices were manually moved
				else if((moved.row(i) - detected.row(i)).squaredNorm() > 1.)
				{
					fixed_V(count) = i;
					count++;
				}
			}
			fixed_V.conservativeResize(count);
		}
		else
			fixed_V = boundary;

		lloyd_relaxation(points, fixed_V, lloyd_iterations, hull_vertices, hull_faces);
		compute_triangulation();
	}

	void Mesh::vertex_degree(Eigen::VectorXi & degree)
	{
		cellogram::vertex_degree(triangles, degree);
	}

	void Mesh::detect_vertices(const Eigen::MatrixXd &V, const DetectionParams &params)
	{
		detected.resize(0, 0); // detected (unmoved) point positions
		points.resize(0, 0); // relaxed point positions
		triangles.resize(0, 0); // triangular mesh
		adj.clear(); // adjaceny list of triangluar mesh
		vertex_to_tri.clear();
		boundary.resize(0); // list of vertices on the boundary

		if (V.size() == 0)
			return;

		this->params = params;
		detected = V;

		moved = detected;
		points = detected;
		vertex_status_fixed.resize(points.rows(), 1);
		vertex_status_fixed.setZero();
		solved_vertex.resize(points.rows(), 1);
		solved_vertex.setConstant(false);

		if (V.rows() < 3)
			return;

		//loose_convex_hull(moved, boundary, 6); moved to compute_triangulation
		compute_triangulation();

		// automatically load params if available

	}

	void Mesh::delete_vertex(const int index, bool recompute_triangulation)
	{
		// Delete vertex
		removeRow(detected, index);
		removeRow(moved, index);
		removeRow(solved_vertex, index);
		removeRow(vertex_status_fixed, index);

		// Delete entry in params
		if (params.A.size() > 0)
		{
			params.remove_index(index);
		}

		for (int i = 0; i < boundary.size(); ++i)
		{
			if (boundary(i) > index)
				--boundary(i);
		}
		for (int i = 0; i < added_by_untangler.size(); ++i)
		{
			if (added_by_untangler(i) == index){
				removeRow(added_by_untangler, index);
				break;
			}
		}

		for (int i = 0; i < added_by_untangler.size(); ++i)
		{
			if (added_by_untangler(i) > index)
				--added_by_untangler(i);
		}
		if (recompute_triangulation)
		{
			reset();
		}
		else
		{
			// delete from points
			removeRow(points, index);

			// delete triangles
			std::vector<int> ind;
			ind = vertex_to_tri[index];
			std::sort(ind.begin(), ind.end());

			for (int i = ind.size()-1; i >= 0; i--)
			{
				removeRow(triangles,ind[i]);
			}
			// lower index of values higher than index
			for (int i = 0; i < triangles.rows(); i++)
			{
				for (int j = 0; j < triangles.cols(); j++)
				{
					if (triangles(i, j) > index)
						triangles(i, j) = triangles(i, j) - 1;
				}
			}
			adjacency_list(triangles, adj);
			generate_vertex_to_tri();
		}
	}

	void Mesh::add_vertex(Eigen::Vector3d & new_point, bool must_reset)
	{
		// Check if vertex already exists
		Eigen::MatrixXd tmp = detected.rowwise() - new_point.transpose();
		Eigen::MatrixXd d = tmp.rowwise().norm();
		if (d.minCoeff() == 0)
		{
			// point is a duplicate
			return;
		}

		// Add vertex
		{
			Eigen::MatrixXd tmp(detected.rows() + 1, detected.cols());
			tmp.block(0, 0, detected.rows(), detected.cols()) = detected;
			tmp.row(detected.rows()) = new_point.transpose();
			detected = tmp;
		}
		// Add vertex to moved
		{
			Eigen::MatrixXd tmp(moved.rows() + 1, moved.cols());
			tmp.block(0, 0, moved.rows(), moved.cols()) = moved;
			tmp.row(moved.rows()) = new_point.transpose();
			moved = tmp;
		}
		// Add new entry to solved_vertex
		Eigen::Matrix<bool, Eigen::Dynamic,1> tmp_bool;
		tmp_bool.resize(solved_vertex.rows()+1);
		tmp_bool.block(0, 0, solved_vertex.rows(), solved_vertex.cols()) = solved_vertex;
		tmp_bool(solved_vertex.rows()) = false;
		solved_vertex = tmp_bool;

		// Add new entry to vertex_status_fixed
		Eigen::MatrixXi tmp_i;
		tmp_i.resize(vertex_status_fixed.rows() + 1, vertex_status_fixed.cols());
		tmp_i.block(0, 0, vertex_status_fixed.rows(), vertex_status_fixed.cols()) = vertex_status_fixed;
		tmp_i(vertex_status_fixed.rows()) = 0;
		vertex_status_fixed = tmp_i;

		// Add zero row to params
		params.push_back_const(0);

		if(must_reset)
			reset();
	}

	void Mesh::local_update(Eigen::VectorXi &local2global, const int global_to_remove, Eigen::MatrixXi & new_triangles)
	{
		//decide if to remove is local or global (better local)
		//remove vertex to_remove from points detected params (ie fix the existing method) delete_vertex(local2global(local_to_remove), false); and update triangulation and the local2global important
		delete_vertex(global_to_remove, false);
		Eigen::MatrixXi tGlobal = Eigen::MatrixXi(new_triangles.rows(), 3);
		for (int i = 0; i < new_triangles.rows(); i++)
		{
			for (int j = 0; j < 3; j++)
			{
				const int gindex = local2global(new_triangles(i, j));
				assert(gindex != global_to_remove);
				tGlobal(i, j) = gindex -(gindex >= global_to_remove ? 1 : 0);
			}

		}

		Eigen::MatrixXi tmp = triangles;
		triangles.resize(triangles.rows() + tGlobal.rows(), triangles.cols());

		triangles << tmp, tGlobal;

		adjacency_list(triangles, adj);
		generate_vertex_to_tri();
	}

	void Mesh::update_triangles_from_split(const Eigen::VectorXi & t_ind_old, const  Eigen::MatrixXi & t1, const Eigen::MatrixXi & t2)
	{
		// first remove all the old triangles
		for (int i = t_ind_old.size()-1; i >= 0; i--)
		{
			removeRow(triangles, t_ind_old(i));
		}

		int nT = triangles.rows();

		// append the new triangles and return their indices in triangle
		int index = triangles.rows();

		triangles.conservativeResize(triangles.rows() + t1.rows() + t2.rows(), 3);
		if (t1.size() > 0)
		{
			triangles.block(index, 0, t1.rows(), 3) = t1;
			index += t1.rows();
		}
		if (t2.size() > 0)
		{
			triangles.block(index, 0, t2.rows(), 3) = t2;
			index += t2.rows();
		}
		assert(index == triangles.rows());
		adjacency_list(triangles, adj);
		generate_vertex_to_tri();
	}

	void Mesh::mark_vertex_as_solved(const Eigen::VectorXi & region_interior)
	{
		for (int i = 0; i < region_interior.size(); i++)
		{
			solved_vertex(region_interior(i)) = true;
		}
	}

	void Mesh::get_physical_bounding_box(double scaling, Eigen::Vector2d & min, Eigen::Vector2d & max) const
	{
		Eigen::RowVector3d maxVal = points.colwise().maxCoeff();
		Eigen::RowVector3d minVal = points.colwise().minCoeff();

		max = maxVal.block<1,2>(0, 0)*scaling;
		min = minVal.block<1,2>(0, 0)*scaling;

		// std::cout << "max:\n" << max << "\n\nmin:\n" << min << std::endl;
	}

	void Mesh::get_background_mesh(double scaling, Eigen::MatrixXd &V, Eigen::MatrixXi &F, Eigen::VectorXd &S, double padding) const {
		Eigen::MatrixXd BV;
		Eigen::MatrixXi BF;
		V = points.leftCols<2>();
		igl::bounding_box(V, padding / scaling, BV, BF);
		assert(BV.rows() == 4);

		V.resize(points.rows() + BV.rows(), 2);
		V.topRows(points.rows()) = points.leftCols<2>();
		V.bottomRows(BV.rows()) = BV;

		delaunay_triangulation(V, F);
		V *= scaling;

		S.resize(V.rows());
		S.head(points.rows()) = (detected - points).rowwise().norm() * scaling;
		S.tail(BV.rows()).setZero();
	}

	void Mesh::local_update(Eigen::VectorXi & local2global, Eigen::MatrixXd & new_points, Eigen::MatrixXi & new_triangles, Eigen::VectorXi & old_triangles)
	{
		for (int i = 0; i < local2global.size(); i++)
		{
			const int global_index = local2global(i);
			points.row(global_index) = new_points.row(i);

		}

		Eigen::MatrixXi tGlobal = Eigen::MatrixXi(new_triangles.rows(), 3);
		for (int i = 0; i < new_triangles.rows(); i++)
		{
			for (int j = 0; j < 3; j++)
			{
				tGlobal(i, j) = local2global(new_triangles(i, j));
			}

		}

		replaceTriangles(tGlobal, old_triangles, triangles);

		adjacency_list(triangles, adj);
		generate_vertex_to_tri();
	}

	void Mesh::final_relax(const Eigen::VectorXi & expanded_boundary)
	{
		int n = points.rows();
		////Find vertices that have lower connectivity than 6

		Eigen::VectorXi neighCount;
		vertex_degree(neighCount);

		// Determine fixed vertices based on connectivity and bounding box
		Eigen::VectorXi indFixed = Eigen::VectorXi::Zero(n);

		for (size_t i = 0; i < n; i++)
		{
			if (neighCount(i) != 6)
			{
				indFixed(i) = 1;
			}
		}

		// fix vertices on the boundary and the ones connected to the boundary
		for (size_t i = 0; i < expanded_boundary.rows(); i++)
		{
			indFixed(expanded_boundary(i)) = 1;
		}

		//////PLEASE USE ME
		//igl::opengl::glfw::Viewer viewer;

		//viewer.data().set_mesh(points, triangles);
		//Eigen::MatrixXd cc(n, 3);
		//for (int i = 0; i < indFixed.rows(); ++i) {
		//	if(indFixed(i) == 1)
		//		cc.row(i) = Eigen::RowVector3d(1, 0, 0);
		//	else
		//		cc.row(i) = Eigen::RowVector3d(0, 0, 0);
		//}
		//viewer.data().set_points(points, cc);
		//viewer.data().point_size = float(8);
		//viewer.core.set_rotation_type(igl::opengl::ViewerCore::RotationType::ROTATION_TYPE_NO_ROTATION);
		//viewer.core.orthographic = true;
		//viewer.core.is_animating = true;
		//viewer.launch();

		// Rearrange coordinates and triangle indices to have free vertices first...
		//MatrixXd xRearranged = MatrixXd::Zero(n, 1);
		Eigen::SparseVector<double> xRearranged(n);
		Eigen::SparseVector<double> yRearranged(n);
		Eigen::VectorXi indicesMapping = Eigen::VectorXi::Zero(n);
		Eigen::MatrixXi trianglesRearranged = Eigen::MatrixXi::Zero(triangles.rows(), 3);

		int c = 0;
		for (size_t i = 0; i < n; i++)
		{
			if (indFixed(i) == 0)
			{
				indicesMapping(i) = c;
				xRearranged.fill(c) = points(i, 0);
				yRearranged.fill(c) = points(i, 1);

				c++;
			}
		}
		int nFree = c;

		// and then the fixed vertices
		for (size_t i = 0; i < n; i++)
		{
			if (indFixed(i) == 1)
			{
				indicesMapping(i) = c;
				xRearranged.fill(c) = points(i, 0);
				yRearranged.fill(c) = points(i, 1);

				c++;
			}
		}

		// rearrange triangles such that it is congruent with the newly arranged coordinates
		for (size_t j = 0; j < triangles.rows(); j++)
		{
			for (size_t k = 0; k < 3; k++)
			{
				trianglesRearranged(j, k) = indicesMapping(triangles(j, k));
			}
		}

		// Generate Laplacian
		Eigen::VectorXd diag = Eigen::VectorXd::Zero(n);
		Eigen::SparseMatrix<double> L(n, n);
		typedef Eigen::Triplet<int> Trip;
		std::vector< Trip > tripletList;
		tripletList.reserve(n * 7);

		for (size_t i = 0; i < trianglesRearranged.rows(); i++)
		{
			for (size_t j = 0; j < 3; j++)
			{
				tripletList.push_back(Trip(trianglesRearranged(i, j), trianglesRearranged(i, (j + 1) % 3), -1));
				tripletList.push_back(Trip(trianglesRearranged(i, (j + 1) % 3), trianglesRearranged(i, j), -1));
				diag(trianglesRearranged(i, j))++;
			}
		}

		for (size_t i = 0; i < diag.rows(); i++)
		{
			tripletList.push_back(Trip(i, i, diag(i)));
		}

		L.setFromTriplets(tripletList.begin(), tripletList.end());

		// Force all non-zeros to be one
		for (int k = 0; k<L.outerSize(); ++k)
		{
			for (Eigen::SparseMatrix<double>::InnerIterator it(L, k); it; ++it)
			{
				if (it.value() < 0)
				{
					L.coeffRef(it.row(), it.col()) = -1;
				}
			}
		}

		// Solve for xNew and yNew
		Eigen::SparseMatrix<double>  Li = L.block(0, 0, nFree, nFree);
		Eigen::SparseMatrix<double>  Lb = L.block(0, nFree, nFree, L.rows() - nFree);

		//SparseMatrix<int>  Lii = Li.inverse();
		Eigen::SimplicialLDLT<Eigen::SparseMatrix<double> > solver;
		solver.compute(Li);
		if (solver.info() != Eigen::Success) {
			// decomposition failed
			return;
		}

		Eigen::SparseVector<double> xB(L.rows() - nFree);
		Eigen::SparseVector<double> yB(L.rows() - nFree);
		for (size_t i = 0; i < L.rows() - nFree; i++)
		{
			xB.fill(i) = xRearranged.coeffRef(nFree + i);
			yB.fill(i) = yRearranged.coeffRef(nFree + i);
		}
		Eigen::SparseVector<double> tmp = -Lb * xB;

		Eigen::VectorXd xNew = solver.solve(Eigen::VectorXd(tmp));

		tmp = -Lb * yB;
		Eigen::VectorXd yNew = solver.solve(Eigen::VectorXd(tmp));

		// Overwrite the free vertices of xRearranged and yRearranged
		for (size_t i = 0; i < nFree; i++)
		{
			xRearranged.coeffRef(i) = xNew(i);
			yRearranged.coeffRef(i) = yNew(i);
		}

		// use indices mapping to overwrite "points" with the newly calculated coordinates
		for (size_t i = 0; i < indicesMapping.rows(); i++)
		{
			points(i,0) = xRearranged.coeffRef(indicesMapping(i));
			points(i,1) = yRearranged.coeffRef(indicesMapping(i));
		}
	}

	void Mesh::generate_vertex_to_tri()
	{
		vertex_to_tri.clear();
		vertex_to_tri.resize(points.rows());

		for (int f = 0; f < triangles.rows(); ++f) {
			for (int lv = 0; lv < triangles.cols(); ++lv)
			{
				const int v_index = triangles(f, lv);
				vertex_to_tri[v_index].push_back(f);
			}
		}
	}

	bool Mesh::untangle()
	{
		bool has_changed_points = false;
		triangles.resize(0, 0); // triangular mesh
		adj.clear(); // adjaceny list of triangluar mesh
		vertex_to_tri.clear();

		added_by_untangler.resize(0);
		deleted_by_untangler.resize(0, 0);

		Eigen::MatrixXd newPts;
		std::vector<int> dropped;
		// std::cout<<points<<std::endl;
		cellogram::PointsUntangler::pointsUntangler(moved, triangles, dropped, newPts);
		// assert(moved.rows() - dropped.size() + newPts.rows() == triangles.maxCoeff() - 1);

		if (newPts.rows() > 0 || !dropped.empty())
		{
			has_changed_points = true;
		}

		int old_size = added_by_untangler.size();
		added_by_untangler.conservativeResize(old_size + newPts.rows());

		for (int i = 0; i < newPts.rows(); ++i) {

			Eigen::Vector3d tmp; tmp.setZero();
			for (int j = 0; j < newPts.cols(); ++j)
				tmp(j) = newPts(i, j);

			added_by_untangler(old_size + i) = detected.rows();
			add_vertex(tmp, false);
		}
		points = moved;

		solved_vertex.setConstant(false);
		vertex_status_fixed.setZero();

		//Now mesh is valid, but it has to many points....
		generate_vertex_to_tri();

		old_size = deleted_by_untangler.size();
		deleted_by_untangler.conservativeResize(old_size + dropped.size(), moved.cols());
		std::sort(dropped.begin(), dropped.end());

		for (int i = dropped.size() - 1; i >= 0; i--)
		{
			const int gid = dropped[i];
			deleted_by_untangler.row(old_size++) = moved.row(gid);
			delete_vertex(gid, false);
		}

		assert(triangles.maxCoeff() < points.rows());
		assert(triangles.minCoeff() >= 0);

		adjacency_list(triangles, adj);
		generate_vertex_to_tri();

		return has_changed_points;
	}

	void Mesh::clear()
	{
		detected.resize(0, 0); // detected (unmoved) point positions
		moved.resize(0, 0); // relaxed point positions
		points.resize(0, 0); // relaxed point positions
		triangles.resize(0, 0); // triangular mesh
		adj.clear(); // adjaceny list of triangluar mesh
		vertex_to_tri.clear();
		boundary.resize(0); // list of vertices on the boundary

		solved_vertex.resize(0);
		vertex_status_fixed.resize(0);
		added_by_untangler.resize(0);
		deleted_by_untangler.resize(0, 0);

		params.clear();
	}

	void Mesh::save(nlohmann::json &data)
	{
		data["detected"] = json::object();
		write_json_mat(detected, data["detected"]);

		data["moved"] = json::object();
		write_json_mat(moved, data["moved"]);

		data["points"] = json::object();
		write_json_mat(points, data["points"]);

		data["displacement"] = json::object();
		write_json_mat((detected-points).eval(), data["displacement"]);

		data["triangles"] = json::object();
		write_json_mat(triangles, data["triangles"]);

		data["boundary"] = json::object();
		write_json_mat(boundary, data["boundary"]);

		data["params"] = json::object();

		params.save(data["params"]);
	}

	// void Mesh::save(const std::string & path)
	// {
	// 	{
	// 		std::ofstream out(path + "/detected.vert");
	// 		out << detected << std::endl;
	// 		out.close();
	// 	}

	// 	{
	// 		std::ofstream out(path + "/moved.vert");
	// 		out << moved << std::endl;
	// 		out.close();
	// 	}

	// 	{
	// 		std::ofstream out(path + "/points.vert");
	// 		out << points << std::endl;
	// 		out.close();
	// 	}

	// 	{
	// 		std::ofstream out(path + "/displacement.txt");
	// 		out << (points-detected) << std::endl;
	// 		out.close();
	// 	}

	// 	{
	// 		std::ofstream out(path + "/mesh.tri");
	// 		out << triangles << std::endl;
	// 		out.close();
	// 	}

	// 	{
	// 		std::ofstream out(path + "/boundary.txt");
	// 		out << boundary << std::endl;
	// 		out.close();
	// 	}

	// 	params.save(path);
	// }

	void Mesh::reset()
	{
		//points = detected;
		points = moved;
		solved_vertex.setConstant(false);

		//recompute boundary

		//compute_triangulation();
	}

	void Mesh::compute_triangulation()
	{
		if (points.size() == 0)
			return;
		// delaunay_triangulation(points, triangles);

		loose_convex_hull(moved, boundary, 6);
		constrained_delaunay_triangulation(points, boundary, triangles);

		// Calculate the graph adjancency
		adjacency_list(triangles, adj);
		generate_vertex_to_tri();

	}

}// namespace cellogram


//---------------------------------------------------------------------------//
//!
//! \file   Utility_Measurement.hpp
//! \author Alex Robinson
//! \brief  The measurement class declaration. This object is based of of the
//!         measurement class in the boost::units examples
//!
//---------------------------------------------------------------------------//

#ifndef UTILITY_MEASUREMENT_HPP
#define UTILITY_MEASUREMENT_HPP

// Boost Includes
#include <boost/units/config.hpp>
#include <boost/units/operators.hpp>
#include <boost/typeof/typeof.hpp>

// Trilinos Includes
#include <Teuchos_ScalarTraits.hpp>

// FRENSIE Includes
#include "Utility_PrintableObject.hpp"
#include "Utility_ContractException.hpp"

namespace Utility{

/*! The measurement class
 *
 * This class wraps is meant to be used as any typical scalar type
 * (e.g. double). It is designed to keep track of and propagate the
 * uncertainty of a value (like one would with a measured quantity).
 */
template<typename T>
class Measurement : public PrintableObject
{

private:

  // The scalar traits typedef
  typedef Teuchos::ScalarTraits<T> ST;

public:

  //! The typedef for this type
  typedef Measurement<T> ThisType;

  //! The typedef for the value type
  typedef T ValueType;

  //! Constructor
  Measurement( const ValueType& value = ValueType(),
	       const ValueType& uncertainty = ValueType() );

  //! Copy constructor
  Measurement( const ThisType& other_measurement );

  //! Destructor
  ~Measurement()
  { /* ... */ }

  //! Print method
  void print( std::ostream& os ) const;

  //! Return the value of the measurement
  const ValueType& getValue() const;

  //! Return the uncertainty of the measurement
  const ValueType& getUncertainty() const;

  //! Return the relative uncertainty of the measurement
  const ValueType getRelativeUncertainty() const;

  //! Return the lower bound of the measurement
  const ValueType getLowerBound() const;

  //! Return the upper bound of the measurement
  const ValueType getUpperBound() const;

  //! Implicit conversion to value type
  operator ValueType() const;

  //! In-place addition operator
  ThisType& operator+=( const ValueType& value );

  //! In-place addition operator
  ThisType& operator+=( const ThisType& other_measurement );

  //! In-place subtraction operator
  ThisType& operator-=( const ValueType& value );

  //! In-place subtraction operator
  ThisType& operator-=( const ThisType& other_measurement );

  //! In-place multiplication operator
  ThisType& operator*=( const ValueType& value );

  //! In-place multiplication operator
  ThisType& operator*=( const ThisType& other_measurement );

  //! In-place division operator
  ThisType& operator/=( const ValueType& value );

  //! In-place division operator
  ThisType& operator/=( const ThisType& other_measurement );

private:

  // The measurement value
  ValueType d_value;

  // The measurement uncertainty
  ValueType d_uncertainty;
};

//! Addition operator
template<typename T>
inline Measurement<T> operator+( T lhs, const Measurement<T>& rhs )
{
  // Make sure nested conditions are met
  testNestedConditionsBegin(1);

  return (Measurement<T>( lhs, T(0) ) += rhs);

  testNestedConditionsEnd(1);
}

//! Addition operator
template<typename T>
inline Measurement<T> operator+( const Measurement<T>& lhs, T rhs )
{
  // Make sure nested conditions are met
  testNestedConditionsBegin(1);

  return (Measurement<T>( lhs ) += Measurement<T>( rhs, T(0) ));

  testNestedConditionsEnd(1);
}

//! Addition operator
template<typename T>
inline Measurement<T> operator+( const Measurement<T>& lhs,
				 const Measurement<T>& rhs )
{
  // Make sure nested conditions are met
  testNestedConditionsBegin(1);

  return (Measurement<T>( lhs ) += rhs );

  testNestedConditionsEnd(1);
}

//! Subtraction operator
template<typename T>
inline Measurement<T> operator-( T lhs, const Measurement<T>& rhs )
{
  // Make sure nested conditions are met
  testNestedConditionsBegin(1);

  return (Measurement<T>( lhs, T(0) ) -= rhs);

  testNestedConditionsEnd(1);
}

//! Subtraction operator
template<typename T>
inline Measurement<T> operator-( const Measurement<T>& lhs, T rhs )
{
  // Make sure nested conditions are met
  testNestedConditionsBegin(1);

  return (Measurement<T>( lhs ) -= Measurement<T>( rhs, T(0) ));

  testNestedConditionsEnd(1);
}

//! Subtraction operator
template<typename T>
inline Measurement<T> operator-( const Measurement<T>& lhs,
				 const Measurement<T>& rhs )
{
  // Make sure nested conditions are met
  testNestedConditionsBegin(1);

  return (Measurement<T>( lhs ) -= rhs );

  testNestedConditionsEnd(1);
}

//! Multiplication operator
template<typename T>
inline Measurement<T> operator*( T lhs, const Measurement<T>& rhs )
{
  // Make sure nested conditions are met
  testNestedConditionsBegin(1);

  return (Measurement<T>( lhs, T(0) ) *= rhs);

  testNestedConditionsEnd(1);
}

//! Multiplication operator
template<typename T>
inline Measurement<T> operator*( const Measurement<T>& lhs, T rhs )
{
  // Make sure nested conditions are met
  testNestedConditionsBegin(1);

  return (Measurement<T>( lhs ) *= Measurement<T>( rhs, T(0) ));

  testNestedConditionsEnd(1);
}

//! Multiplication operator
template<typename T>
inline Measurement<T> operator*( const Measurement<T>& lhs,
				 const Measurement<T>& rhs )
{
  // Make sure nested conditions are met
  testNestedConditionsBegin(1);

  return (Measurement<T>( lhs ) *= rhs );

  testNestedConditionsEnd(1);
}

//! Division operator
template<typename T>
inline Measurement<T> operator/( T lhs, const Measurement<T>& rhs )
{
  // Make sure nested conditions are met
  testNestedConditionsBegin(1);

  // Make sure nested conditions are met
  return (Measurement<T>( lhs, T(0) ) /= rhs);

  testNestedConditionsEnd(1);
}

//! Division operator
template<typename T>
inline Measurement<T> operator/( const Measurement<T>& lhs, T rhs )
{
  // Make sure nested conditions are met
  testNestedConditionsBegin(1);

  return (Measurement<T>( lhs ) /= Measurement<T>( rhs, T(0) ));

  testNestedConditionsEnd(1);
}

//! Division operator
template<typename T>
inline Measurement<T> operator/( const Measurement<T>& lhs,
				 const Measurement<T>& rhs )
{
  // Make sure nested conditions are met
  testNestedConditionsBegin(1);

  return (Measurement<T>( lhs ) /= rhs );

  testNestedConditionsEnd(1);
}

//! Overload of sqrt for a measurement
template<typename T>
inline Measurement<T> sqrt( const Measurement<T>& x )
{
  // Make sure the measurement is valid
  testPrecondition( x.getValue() >= 0.0 );

  const T new_value = std::sqrt( x.getValue() );

  const T propagated_uncertainty = 0.5*(new_value/x.getValue())*
    x.getUncertainty();

  // Make sure reasonable values have been calculated
  testPostcondition( !Teuchos::ScalarTraits<T>::isnaninf( new_value ) );
  testPostcondition( !Teuchos::ScalarTraits<T>::isnaninf(
						    propagated_uncertainty ) );

  return Measurement<T>( new_value, propagated_uncertainty );
}

//! Overload of pow for a measurement
template<typename T, typename ExponentType>
inline Measurement<T> pow( const Measurement<T>& x,
			   const ExponentType exponent )
{
  const T new_value = std::pow( x.getValue(), exponent );

  const T propagated_uncertainty = fabs(exponent*(new_value/x.getValue()))*
    x.getUncertainty();

  // Make sure reasonable values have been calculated
  testPostcondition( !Teuchos::ScalarTraits<T>::isnaninf( new_value ) );
  testPostcondition( !Teuchos::ScalarTraits<T>::isnaninf(
						    propagated_uncertainty ) );
  testPostcondition( propagated_uncertainty >= 0.0 );

  return Measurement<T>( new_value, propagated_uncertainty );
}

} // end Utility namespace

namespace boost{

namespace units{

//! Specialization of the boost::units::power_typeof_helper
template<typename Y, long N, long D>
struct power_typeof_helper<Utility::Measurement<Y>,static_rational<N,D> >
{
  typedef Utility::Measurement<typename power_typeof_helper<Y,static_rational<N,D> >::type> type;

  static type value( const Utility::Measurement<Y>& x)
  {
    const static_rational<N,D> rational;

    const Y rational_power = Y(rational.numerator())/Y(rational.denominator());

    return Utility::pow( x, rational_power );
  }
};

//! Specialization of the boost::units::root_typeof_helper
template<typename Y, long N, long D>
struct root_typeof_helper<Utility::Measurement<Y>,static_rational<N,D> >
{
  typedef Utility::Measurement<typename root_typeof_helper<Y,static_rational<N,D> >::type> type;

  static type value( const Utility::Measurement<Y>& x )
  {
    const static_rational<N,D> rational;

    // Compute D/N instead of N/D since we're interested in the root
    const Y rational_power = Y(rational.denominator())/Y(rational.numerator());

    return Utility::pow( x, rational_power );
  }
};

} // end units namespace

} // end boost namespace

namespace Teuchos{

//! Partial specialization of Teuchos::ScalarTraits for the Measurement class
template<typename T>
struct ScalarTraits<Utility::Measurement<T> >
{
  typedef Utility::Measurement<T> Measurement;
  typedef T magnitudeType;
  typedef typename Teuchos::ScalarTraits<T>::halfPrecision halfPrecision;
  typedef typename Teuchos::ScalarTraits<T>::doublePrecision doublePrecision;

  static const bool isComplex = Teuchos::ScalarTraits<T>::isComplex;
  static const bool isOrdinal = Teuchos::ScalarTraits<T>::isOrdinal;
  static const bool isComparable = Teuchos::ScalarTraits<T>::isComparable;
  static const bool hasMachineParameters = Teuchos::ScalarTraits<T>::hasMachineParameters;

  static inline magnitudeType eps() { return ScalarTraits<magnitudeType>::eps(); }
  static inline magnitudeType sfmin() { return ScalarTraits<magnitudeType>::sfmin(); }
  static inline magnitudeType base() { return ScalarTraits<magnitudeType>::base(); }
  static inline magnitudeType prec() { return ScalarTraits<magnitudeType>::prec(); }
  static inline magnitudeType t() { return ScalarTraits<magnitudeType>::t(); }
  static inline magnitudeType rnd() { return ScalarTraits<magnitudeType>::rnd(); }
  static inline magnitudeType emin() { return ScalarTraits<magnitudeType>::emin(); }
  static inline magnitudeType rmin() { return ScalarTraits<magnitudeType>::rmin(); }
  static inline magnitudeType emax() { return ScalarTraits<magnitudeType>::emax(); }
  static inline magnitudeType rmax() { return ScalarTraits<magnitudeType>::rmax(); }
  static inline magnitudeType magnitude(Measurement a) { return ScalarTraits<magnitudeType>::magnitude( a.getValue() ); }
  static inline Measurement zero() { return Measurement( ScalarTraits<magnitudeType>::zero(), 0.0 ); }
  static inline Measurement one() { return Measurement( ScalarTraits<magnitudeType>::zero(), 1.0 ); }
  static inline Measurement conjugate(Measurement a){ return Measurement( ScalarTraits<magnitudeType>::conjugate(a.getValue()), ScalarTraits<magnitudeType>::conjugate(a.getUncertainty()) ); }
  static inline Measurement real(Measurement a){ return Measurement( ScalarTraits<magnitudeType>::real(a.getValue()), ScalarTraits<magnitudeType>::real(a.getUncertainty()) ); }
  static inline Measurement imag(Measurement a){ return Measurement( ScalarTraits<magnitudeType>::imag(a.getValue()), ScalarTraits<magnitudeType>::imag(a.getUncertainty()) ); }
  static inline Measurement nan() { return Measurement( ScalarTraits<magnitudeType>::nan(), ScalarTraits<magnitudeType>::nan() ); }
  static inline bool isnaninf(Measurement a){ return ScalarTraits<magnitudeType>::isnaninf(a.getValue()) || ScalarTraits<magnitudeType>::isnaninf(a.getUncertainty()); }
  static inline void seedrandom(unsigned int s) { ScalarTraits<magnitudeType>::seedrandom(s); }
  static inline Measurement random() { return Measurement( ScalarTraits<magnitudeType>::random(), 0.0 ); }
  static inline std::string name() { return std::string("Measurement<")+std::string(ScalarTraits<magnitudeType>::name())+std::string(">"); }
  static inline Measurement squareroot(Measurement a) { return Utility::sqrt(a); }
  static inline Measurement pow(Measurement a, Measurement b) { return Utility::pow( a, b.getValue() ); }

};

} // end Teuchos namespace

// Register the Measurement class with boost typeof for auto-like type
// deduction when used with the boost::units library
#if BOOST_UNITS_HAS_BOOST_TYPEOF

BOOST_TYPEOF_REGISTER_TEMPLATE(Utility::Measurement, 1)

#endif // end BOOST_UNITS_HAS_BOOST_TYPEOF

//---------------------------------------------------------------------------//
// Template Includes
//---------------------------------------------------------------------------//

#include "Utility_Measurement_def.hpp"

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

#endif // end UTILITY_MEASUREMENT_HPP

//---------------------------------------------------------------------------//
// end Utility_Measurement.hpp
//---------------------------------------------------------------------------//


/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*                                                                           */
/*  This file is part of the library KASKADE 7                               */
/*    see http://www.zib.de/projects/kaskade7-finite-element-toolbox         */
/*                                                                           */
/*  Copyright (C) 2002-2016 Zuse Institute Berlin                            */
/*                                                                           */
/*  KASKADE 7 is distributed under the terms of the ZIB Academic License.    */
/*    see $KASKADE/academic.txt                                              */
/*                                                                           */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#ifndef LINEARSPACE_HH
#define LINEARSPACE_HH

#include <cmath>
#include <type_traits>

#include <boost/version.hpp>
#include <boost/fusion/algorithm.hpp>
#include <boost/fusion/sequence.hpp>

#include "linalg/crsutil.hh"

namespace Kaskade
{
  /// \internal
  // forward declaration
  template <class> class VariableSet;

  namespace LinearSpace_Detail
  {

    template <class Space0, class Space2, int id> struct Copy;

    template <class Space, int id, class VSDescriptions>
    struct Copy<VariableSet<VSDescriptions>,Space,id>
    {
      static void apply(const VariableSet<VSDescriptions>& from, Space& to)
      {
        boost::fusion::at_c<id>(to.data) = boost::fusion::at_c<id>(from.data).coefficients();
        Copy<VariableSet<VSDescriptions>,Space,id-1>::apply(from,to);
      }
    };

    template <class Space, class VSDescriptions>
    struct Copy<VariableSet<VSDescriptions>,Space,0>
    {
      static void apply(const VariableSet<VSDescriptions>& from, Space& to)
      {
        boost::fusion::at_c<0>(to.data) = boost::fusion::at_c<0>(from.data).coefficients();
      }
    };
  }
  /// \endinternal

  /**
   * \ingroup linalgbasic
   * \brief A product space of linear spaces.
   *
   * Access to the components of the product space is provided by the the boost::fusion
   * sequence data:
   * \code
   * LinearProductSpace<double,boost::fusion::vector<Dune::FieldVector<double,2>,Dune::FieldVector<double,3>>> x;
   * Dune::FieldVector<double,3>& comp1 = boost::fusion::at_c<1>(x.data);
   * \endcode
   *
   * Arithmetic operations are delegated componentwise to the heterogeneous subspaces.
   *
   *
   * \tparam Scalar the scalar field type of the linear space
   * \tparam Seq a boost::fusion sequence type defining the variables of the cartesian product
   */
  template <class Scalar_, class Seq>
  class LinearProductSpace
  {
  private:
    typedef LinearProductSpace<Scalar_,Seq> Self;

    // forward declarations (definitions at end of file)
    struct Add;
    struct Sub;
    struct Assign;
    struct ScalarMult;
    struct Axpy;
    struct ScalarProduct;
    struct ScalarProductHack;
    template <typename> struct ReadBlock;
    template <typename> struct WriteBlock;

  public:
    /// scalar type
    typedef Scalar_ Scalar;
    typedef Scalar field_type;

    /// boost::fusion::vector of element vectors.
    typedef Seq Sequence;
    typedef Seq Functions;

    // use with care: default constructed subvectors may not be properly initialized (e.g. size?)
    // LinearProductSpace() {}
    LinearProductSpace() = delete;

    /// Copy constructor
    LinearProductSpace(LinearProductSpace<Scalar,Sequence> const& y): data(y.data) {}

    /// Copy from VariableSet
    template <class VSDescriptions>
    explicit LinearProductSpace(const VariableSet<VSDescriptions>& y)
    {
      *this = y;
    }

    /// Constructor with explicit data
    template <class S>
    explicit LinearProductSpace(S const& init): data(init)
    {}

    template <typename... Args>
    explicit LinearProductSpace(boost::fusion::transform_view<Args...> const& data_) : data(data_)
    {
      applyUnaryOp(Assign(0));
    }

    /**
     *\brief Number of scalar degrees of freedom.
     * This computes the total number of degrees of freedom, i.e. the sum of the dimensions of
     * the components.
     */
    size_t dim() const
    {
      return boost::fusion::accumulate(data,0,[](auto dim, auto const& v) { return dim+v.dim(); });
    }

    /// Assignment from the same type
    Self& operator=(Self const& y) { if (this!=&y) data = y.data; return *this; }

    /// Assignment from a different (hopefully compatible) type
    template <class VSDescriptions>
    Self& operator=(VariableSet<VSDescriptions> const& y)
    {
      using namespace boost::fusion;
      static_assert(result_of::size<Sequence>::type::value == VSDescriptions::noOfVariables,"Numbers of variables do not match.");
      LinearSpace_Detail::Copy<VariableSet<VSDescriptions>,LinearProductSpace,
                               result_of::size<typename VSDescriptions::RepresentationData>::type::value-1>::apply(y,*this);
      return *this;
    } // need not check for self assignment here

    /// Assignment from a different (hopefully compatible) type
    template <class OtherSeq>
    Self& operator=(LinearProductSpace<Scalar,OtherSeq> const& y)
    {
      using namespace boost::fusion;
      static_assert(result_of::size<Sequence>::type::value == result_of::size<OtherSeq>::type::value, "Numbers of variables do not match.");
      data = y.data;
      return *this;
    } // need not check for self assignment here

    /// Assignment from a (hopefully compatible) FunctionSpaceElement
    template <class FunctionSpace, int m>
    Self& operator=(FunctionSpaceElement<FunctionSpace,m> const& fse)
    {
      data = fse.coefficients();
      return *this;
    }

    /// Assignment to constant scalar
    Self& operator=(Scalar a)
    {
      return applyUnaryOp(Assign(a));
    }

    /// Assignment from a (hopefully compatible) boost::fusion iterator range
    template <class First, class Last>
    Self& operator=(boost::fusion::iterator_range<First,Last> range)
    {
      static_assert(boost::fusion::result_of::size<Sequence>::type::value == boost::fusion::result_of::distance<First,Last>::type::value,
                    "Numbers of variables do not match.");
      data = range;
      return *this;
    }

    //

    /// Scaling
    Self& operator*=(Scalar a) { return applyUnaryOp(ScalarMult(a)); }

    /// In place addition
    template <class SequenceY>
    Self& operator+=(LinearProductSpace<Scalar,SequenceY> const& y) {
      return applyBinaryOp(Add(),y); }

    /// In place subtraction
    Self& operator-=(Self const& y) { return applyBinaryOp(Sub(),y); }

    /// this <- this + a*y
    Self& axpy(Scalar a, Self const& y) { return applyBinaryOp(Axpy(a),y); }

    /// Scalar product
    field_type operator*(Self const& y) const {
      // For some unknown reason, this does not work... (will work in more recent fusion version).
      // return boost::fusion::accumulate(boost::fusion::zip(data,y.data),0,ScalarProduct());
      // We therefore use the following ugly hack workaround
      using namespace boost::fusion;
      zip_view<vector<Sequence const&,Sequence const&> > zipped(vector<Sequence const&,Sequence const&>(data,y.data));
      ScalarProductHack sp;
      for_each(zipped,sp);
      return sp.s;
    }

    /// Scalar product
    field_type dot(Self const& y) const { return *this * y; }

    /**
     * \brief DEPRECATED use vectorFromSequence instead
     *
     * Reads the coefficients sequentially from an input iterator.
     * The InIterator's value type must be convertible to field_type.
     */
    template <class InIterator>
    void read(InIterator i)
    {
      vectorFromSequence(*this,i);
    }

    /**
     * \brief Reads the coefficients of the subrange [rbegin,rend[ sequentially from an input iterator.
     * The InIterator's value type must be convertible to field_type.
     */
    template <class InIterator>
    void read(int rbegin, int rend, InIterator i) { boost::fusion::for_each(data,ReadBlock<InIterator>(rbegin,rend,i)); }

    /**
     * \brief DEPRECATED use vectorToSequence instead
     *
     * Writes the coefficients sequentially to an output iterator (flattening).
     * The field_type must be convertible to the OutIterator's value type.
     */
    template <class OutIterator>
    void write(OutIterator i) const
    {
      vectorToSequence(*this,i);
    }

    /**
     * \brief Writes the coefficients of the subrange [rbegin,rend[ sequentially to an output iterator.
     * The InIterator's value type must be convertible to field_type.
     */
    template <class DataOutIter>
    void write(int rbegin, int rend, DataOutIter i) const
    {
      boost::fusion::for_each(data,WriteBlock<DataOutIter>(rbegin,rend,i));
    }

    /// Euclidean Norm
    double two_norm() const { return std::sqrt((*this)*(*this)); }

    /// Data
    Sequence data;

  private:

    // applies a binary operator to the elements of a pair
    template <class BinaryOp>
    struct PairOp
    {
      PairOp(BinaryOp const& op_): op(op_) {}

      template <class Pair> void operator()(Pair p) const {
        op(boost::fusion::at_c<0>(p),boost::fusion::at_c<1>(p));
      }

    private:
      BinaryOp const& op;
    };

    template <class UnaryOp>
    Self& applyUnaryOp(UnaryOp const& op) {
      boost::fusion::for_each(data,op);
      return *this;
    }

    template <class BinaryOp, class SpaceY>
    Self& applyBinaryOp(BinaryOp const& op, SpaceY const& y) {
      using namespace boost::fusion;
      typedef typename SpaceY::Sequence SequenceY;
      zip_view<vector<Sequence&,SequenceY const&> > zipped(vector<Sequence&,SequenceY const&>(data,y.data));
      for_each(zipped,PairOp<BinaryOp>(op));
      return *this;
    }

    struct Add { template <class T, class S> void operator()(T& a, S const& b) const { a += b; } };
    struct Sub { template <class T> void operator()(T& a, T const& b) const { a -= b; } };
    struct Assign {
      Assign(Scalar s_): s(s_) {}
      template <class T> void operator()(T& a) const { a = s; }
    private: Scalar s;
    };

    struct ScalarMult {
      ScalarMult(Scalar s_): s(s_) {}
      template <class Element> void operator()(Element& e) const { e *= s; }
    private: Scalar s;
    };

    struct Axpy
    {
      Axpy(Scalar s_): s(s_) {}
      template <class T> void operator()(T& a, T const& b) const {

        // Funny runtime error could only be avoided by this funny code.
        // Probably a compiler bug.
        // assert(a.size()==b.size());
        std::cout << "";

        a.axpy(s,b);
      }

    private: Scalar s;
    };

    struct ScalarProduct
    {
      template <class T> struct result {};

      template <class Pair, class T> struct result<ScalarProduct(Pair,T)> { typedef field_type type; };
      template <class Pair>
      field_type operator()(Pair const& pair, field_type res) const {
        using namespace boost::fusion;

        return res ;//+ at_c<0>(pair)*at_c<1>(pair);
      }
    };

    // Ugly hack -- see above
    struct ScalarProductHack
    {
      ScalarProductHack(): s(0) {}
      template <class Pair> void operator()(Pair const& p) const { s += boost::fusion::at_c<0>(p) * boost::fusion::at_c<1>(p); }
      mutable field_type s;
    };

    template <class DataOutIter>
    struct WriteBlock
    {

      WriteBlock(int& rbegin_, int& rend_, DataOutIter& out_): rbegin(rbegin_), rend(rend_), out(out_) {}
      template <class VectorBlock> void operator()(VectorBlock const& v) const
      {
        if (rbegin<=0 && rend>0)
          vectorToSequence(v,out);
        --rbegin;
        --rend;
      }
    private:
      int& rbegin;
      int& rend;
      DataOutIter& out;

    };

    template <class DataInIter>
    struct ReadBlock
    {
      ReadBlock(int& rbegin_, int& rend_, DataInIter& in_): rbegin(rbegin_), rend(rend_), in(in_) {}

      template <class VectorBlock> void operator()(VectorBlock& v) const
      {
        if (rbegin<=0 && rend>0)
          vectorFromSequence(v,in);
        --rbegin;
        --rend;
      }
    private:
      int& rbegin;
      int& rend;
      DataInIter& in;

    };

  };

  /**
   * \ingroup linalgbasic
   * \brief Provides access to the m-th component of a product space.
   *
   * This simplifies the access to individual components of a product space, e.g., a variable set of finite
   * element functions. Instead of
   * \code
   * boost::fusion::at_c<m>(x.data)
   * \endcode
   * one can write
   * \code
   * component<m>(x)
   * \endcode
   *
   * \tparam m the index of the component (nonnegative)
   * \tparam Scalar a scalar type
   * \tparam Sequence a boost::fusion sequence type
   *
   * \return a reference to the m-th component
   *
   * \relates LinearProductSpace
   */
  template <int m, class Scalar, class Sequence>
  typename boost::fusion::result_of::at_c<Sequence const,m>::type component(LinearProductSpace<Scalar,Sequence> const& x) { return boost::fusion::at_c<m>(x.data); }

  template <int m, class Scalar, class Sequence>
  typename boost::fusion::result_of::at_c<Sequence,m>::type component(LinearProductSpace<Scalar,Sequence>& x) { return boost::fusion::at_c<m>(x.data); }

  /**
   * \ingroup linalgbasic
   * \brief writes the coefficients of a vector to a flat scalar sequence
   * \related LinearProductSpace<Scalar,Seq>
   */
  template <class Scalar, class Seq, class OutIter>
  OutIter vectorToSequence(LinearProductSpace<Scalar,Seq> const& v, OutIter i)
  {
    boost::fusion::for_each(v.data,[&](auto& x) { i = vectorToSequence(x,i); });
    return i;
  }

  /**
   * \ingroup linalgbasic
   * \brief reads the coefficients of a vector from a flat scalar sequence
   * \related LinearProductSpace<Scalar,Seq>
   */
  template <class Scalar, class Seq, class InIter>
  InIter vectorFromSequence(LinearProductSpace<Scalar,Seq>& v, InIter i)
  {
    boost::fusion::for_each(v.data,[&](auto& x) { i = vectorFromSequence(x,i); });
    return i;
  }

} // end of namespace Kaskade

#endif


///////////////////////////////////////////////////////////////////////////////
// BSD 3-Clause License
//
// Copyright (C) 2019-2020, LAAS-CNRS, New York University, Max Planck Gesellschaft,
//                          University of Edinburgh
// Copyright note valid unless otherwise stated in individual files.
// All rights reserved.
///////////////////////////////////////////////////////////////////////////////

#ifndef CROCODDYL_CORE_NUMDIFF_STATE_HPP_
#define CROCODDYL_CORE_NUMDIFF_STATE_HPP_

#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>

#include "crocoddyl/core/fwd.hpp"
#include "crocoddyl/core/state-base.hpp"

namespace crocoddyl {

template <typename _Scalar>
class StateNumDiffTpl : public StateAbstractTpl<_Scalar> {
 public:
  EIGEN_MAKE_ALIGNED_OPERATOR_NEW

  typedef _Scalar Scalar;
  typedef MathBaseTpl<Scalar> MathBase;
  typedef StateAbstractTpl<_Scalar> Base;
  typedef typename MathBase::VectorXs VectorXs;
  typedef typename MathBase::MatrixXs MatrixXs;

  explicit StateNumDiffTpl(boost::shared_ptr<Base> state);
  virtual ~StateNumDiffTpl();

  virtual VectorXs zero() const;
  virtual VectorXs rand() const;
  virtual void diff(const Eigen::Ref<const VectorXs>& x0, const Eigen::Ref<const VectorXs>& x1,
                    Eigen::Ref<VectorXs> dxout) const;
  virtual void integrate(const Eigen::Ref<const VectorXs>& x, const Eigen::Ref<const VectorXs>& dx,
                         Eigen::Ref<VectorXs> xout) const;
  /**
   * @brief This computes the Jacobian of the diff method by finite
   * differentiation:
   * \f{equation}{
   *    Jfirst[:,k] = diff(int(x_1, dx_dist), x_2) - diff(x_1, x_2)/disturbance
   * \f}
   * and
   * \f{equation}{
   *    Jsecond[:,k] = diff(x_1, int(x_2, dx_dist)) - diff(x_1, x_2)/disturbance
   * \f}
   *
   * @param Jfirst
   * @param Jsecond
   * @param firstsecond
   */
  virtual void Jdiff(const Eigen::Ref<const VectorXs>& x0, const Eigen::Ref<const VectorXs>& x1,
                     Eigen::Ref<MatrixXs> Jfirst, Eigen::Ref<MatrixXs> Jsecond, Jcomponent firstsecond = both) const;
  /**
   * @brief This computes the Jacobian of the integrate method by finite
   * differentiation:
   * \f{equation}{
   *    Jfirst[:,k] = diff( int(x, d_x), int( int(x, dx_dist), dx) )/disturbance
   * \f}
   * and
   * \f{equation}{
   *    Jsecond[:,k] = diff( int(x, d_x), int( x, dx + dx_dist) )/disturbance
   * \f}
   *
   * @param Jfirst
   * @param Jsecond
   * @param firstsecond
   */
  virtual void Jintegrate(const Eigen::Ref<const VectorXs>& x, const Eigen::Ref<const VectorXs>& dx,
                          Eigen::Ref<MatrixXs> Jfirst, Eigen::Ref<MatrixXs> Jsecond,
                          const Jcomponent firstsecond = both, const AssignmentOp op = setto) const;

  virtual void JintegrateTransport(const Eigen::Ref<const VectorXs>& x, const Eigen::Ref<const VectorXs>& dx,
                                   Eigen::Ref<MatrixXs> Jin, const Jcomponent firstsecond = both) const;

  const Scalar& get_disturbance() const;
  void set_disturbance(const Scalar& disturbance);

 private:
  /**
   * @brief This is the state we need to compute the numerical differentiation
   * from.
   */
  boost::shared_ptr<Base> state_;
  /**
   * @brief This the increment used in the finite differentiation and integration.
   */
  Scalar disturbance_;

 protected:
  using Base::has_limits_;
  using Base::lb_;
  using Base::ndx_;
  using Base::nq_;
  using Base::nv_;
  using Base::nx_;
  using Base::ub_;
};

}  // namespace crocoddyl

/* --- Details -------------------------------------------------------------- */
/* --- Details -------------------------------------------------------------- */
/* --- Details -------------------------------------------------------------- */
#include "crocoddyl/core/numdiff/state.hxx"

#endif  // CROCODDYL_CORE_NUMDIFF_STATE_HPP_


/*!
@file
Forward declares `boost::hana::Group`.

@copyright Louis Dionne 2015
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
 */

#ifndef BOOST_HANA_FWD_GROUP_HPP
#define BOOST_HANA_FWD_GROUP_HPP

#include <boost/hana/detail/std/forward.hpp>
#include <boost/hana/fwd/core/datatype.hpp>
#include <boost/hana/fwd/core/operators.hpp>

namespace boost { namespace hana {
    //! @ingroup group-concepts
    //! The `Group` concept represents `Monoid`s where all objects have
    //! an inverse w.r.t. the `Monoid`'s binary operation.
    //!
    //! A [Group][1] is an algebraic structure built on top of a `Monoid`
    //! which adds the ability to invert the action of the `Monoid`'s binary
    //! operation on any element of the set. Specifically, a `Group` is a
    //! `Monoid` `(S, +)` such that every element `s` in `S` has an inverse
    //! (say `s'`) which is such that
    //! @code
    //!     s + s' == s' + s == identity of the Monoid
    //! @endcode
    //!
    //! There are many examples of `Group`s, one of which would be the
    //! additive `Monoid` on integers, where the inverse of any integer
    //! `n` is the integer `-n`. The method names used here refer to
    //! exactly this model.
    //!
    //!
    //! Superclass
    //! ----------
    //! `Monoid`
    //!
    //!
    //! Laws
    //! ----
    //! For all objects `x` of a `Group` `G`, the following laws must be
    //! satisfied:
    //! @code
    //!     plus(x, negate(x)) == zero<G>() // right inverse
    //!     plus(negate(x), x) == zero<G>() // left inverse
    //! @endcode
    //!
    //!
    //! Minimal complete definitions
    //! ----------------------------
    //! 1. `minus`\n
    //! When `minus` is specified, the `negate` method is defaulted by setting
    //! @code
    //!     negate(x) = minus(zero<G>(), x)
    //! @endcode
    //!
    //! 2. `negate`\n
    //! When `negate` is specified, the `minus` method is defaulted by setting
    //! @code
    //!     minus(x, y) = plus(x, negate(y))
    //! @endcode
    //!
    //!
    //! Provided models
    //! ---------------
    //! 1. For non-boolean arithmetic data types\n
    //! A data type `T` is arithmetic if `std::is_arithmetic<T>::%value` is
    //! true. For a non-boolean arithmetic data type `T`, a model of `Group`
    //! is automatically defined by setting
    //! @code
    //!     minus(x, y) = (x - y)
    //!     negate(x) = -x
    //! @endcode
    //!
    //! @note
    //! The rationale for not providing a Group model for `bool` is the same
    //! as for not providing a `Monoid` model.
    //!
    //!
    //! Operators
    //! ---------
    //! For convenience, the following operators are provided as an
    //! equivalent way of calling the corresponding method:
    //! @code
    //!     binary -  ->  minus
    //!     unary -   ->  negate
    //! @endcode
    //!
    //!
    //! Structure-preserving functions
    //! ------------------------------
    //! Let `A` and `B` be two `Group`s. A function `f : A -> B` is said to
    //! be a [Group morphism][2] if it preserves the group structure between
    //! `A` and `B`. Rigorously, for all objects `x, y` of data type `A`,
    //! @code
    //!     f(plus(x, y)) == plus(f(x), f(y))
    //! @endcode
    //! Because of the `Group` structure, it is easy to prove that the
    //! following will then also be satisfied:
    //! @code
    //!     f(negate(x)) == negate(f(x))
    //!     f(zero<A>()) == zero<B>()
    //! @endcode
    //! Functions with these properties interact nicely with `Group`s, which
    //! is why they are given such a special treatment.
    //!
    //!
    //! [1]: http://en.wikipedia.org/wiki/Group_(mathematics)
    //! [2]: http://en.wikipedia.org/wiki/Group_homomorphism
    struct Group { };

    //! Subtract two elements of a group.
    //! @relates Group
    //!
    //! Specifically, this performs the `Monoid` operation on the first
    //! argument and on the inverse of the second argument, thus being
    //! equivalent to:
    //! @code
    //!     minus(x, y) == plus(x, negate(y))
    //! @endcode
    //!
    //!
    //! Cross-type version of the method
    //! --------------------------------
    //! The `minus` method is "overloaded" to handle distinct data types
    //! with certain properties. Specifically, `minus` is defined for
    //! _distinct_ data types `A` and `B` such that
    //! 1. `A` and `B` share a common data type `C`, as determined by the
    //!    `common` metafunction
    //! 2. `A`, `B` and `C` are all `Group`s when taken individually
    //! 3. `to<C> : A -> B` and `to<C> : B -> C` are `Group`-embeddings, as
    //!    determined by the `is_embedding` metafunction.
    //!
    //! The definition of `minus` for data types satisfying the above
    //! properties is obtained by setting
    //! @code
    //!     minus(x, y) = minus(to<C>(x), to<C>(y))
    //! @endcode
    //!
    //!
    //! Example
    //! -------
    //! @snippet example/group.cpp minus
#ifdef BOOST_HANA_DOXYGEN_INVOKED
    constexpr auto minus = [](auto&& x, auto&& y) -> decltype(auto) {
        return tag-dispatched;
    };
#else
    template <typename T, typename U, typename = void>
    struct minus_impl;

    struct _minus {
        template <typename X, typename Y>
        constexpr decltype(auto) operator()(X&& x, Y&& y) const {
            return minus_impl<
                typename datatype<X>::type, typename datatype<Y>::type
            >::apply(
                detail::std::forward<X>(x),
                detail::std::forward<Y>(y)
            );
        }
    };

    constexpr _minus minus{};
#endif

    //! Return the inverse of an element of a group.
    //! @relates Group
    //!
    //!
    //! Example
    //! -------
    //! @snippet example/group.cpp negate
#ifdef BOOST_HANA_DOXYGEN_INVOKED
    constexpr auto negate = [](auto&& x) -> decltype(auto) {
        return tag-dispatched;
    };
#else
    template <typename G, typename = void>
    struct negate_impl;

    struct _negate {
        template <typename X>
        constexpr decltype(auto) operator()(X&& x) const {
            return negate_impl<typename datatype<X>::type>::apply(
                detail::std::forward<X>(x)
            );
        }
    };

    constexpr _negate negate{};
#endif

    template <>
    struct operators::of<Group>
        : decltype(minus), decltype(negate)
    { };
}} // end namespace boost::hana

#endif // !BOOST_HANA_FWD_GROUP_HPP


/*
 Copyright (C) 2016 Quaternion Risk Management Ltd
 All rights reserved.

 This file is part of ORE, a free-software/open-source library
 for transparent pricing and risk analysis - http://opensourcerisk.org

 ORE is free software: you can redistribute it and/or modify it
 under the terms of the Modified BSD License.  You should have received a
 copy of the license along with this program.
 The license is also available online at <http://opensourcerisk.org>

 This program is distributed on the basis that it will form a useful
 contribution to risk analytics and model standardisation, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
*/

/*! \file ored/configuration/yieldcurveconfig.hpp
    \brief Yield curve configuration classes
    \ingroup configuration
*/

#pragma once

#include <boost/none.hpp>
#include <boost/optional.hpp>
#include <boost/shared_ptr.hpp>
#include <map>
#include <ored/configuration/curveconfig.hpp>
#include <ored/utilities/xmlutils.hpp>
#include <ql/patterns/visitor.hpp>
#include <ql/types.hpp>
#include <set>

namespace ore {
namespace data {
using std::string;
using std::vector;
using std::set;
using std::pair;
using std::map;
using boost::optional;
using ore::data::XMLNode;
using QuantLib::AcyclicVisitor;
using QuantLib::Real;

//! Base class for yield curve segments.
/*!
  \ingroup configuration
*/
class YieldCurveSegment : public XMLSerializable {
public:
    //! supported segment types
    enum class Type {
        Zero,
        ZeroSpread,
        Discount,
        Deposit,
        FRA,
        Future,
        OIS,
        Swap,
        AverageOIS,
        TenorBasis,
        TenorBasisTwo,
        BMABasis,
        FXForward,
        CrossCcyBasis,
        CrossCcyFixFloat,
        DiscountRatio
    };
    //! Default destructor
    virtual ~YieldCurveSegment() {}

    //! \name Serialisation
    //@{
    virtual void fromXML(XMLNode* node) = 0;
    virtual XMLNode* toXML(XMLDocument& doc) = 0;
    //@}

    //! \name Inspectors
    //@{
    Type type() const { return type_; }
    // TODO: why typeID?
    const string& typeID() const { return typeID_; }
    const string& conventionsID() const { return conventionsID_; }
    const vector<pair<string, bool>>& quotes() const { return quotes_; }
    //@}

    //! \name Visitability
    //@{
    virtual void accept(AcyclicVisitor&);
    //@}

protected:
    //! \name Constructors
    //@{
    //! Default constructor
    YieldCurveSegment() {}
    //! Detailed constructor - assumes all quotes are mandatory
    YieldCurveSegment(const string& typeID, const string& conventionsID, const vector<string>& quotes);
    //@}

    //! Quote and optional flag pair
    vector<pair<string, bool>> quotes_;

    //! Utility to build a quote, optional flag defaults to false
    pair<string, bool> quote(const string& name, bool opt = false) { return make_pair(name, opt); }

    //! Utility method to read quotes from XML
    void loadQuotesFromXML(XMLNode* node);
    //! Utility method to write quotes to XML
    XMLNode* writeQuotesToXML(XMLDocument& doc);

private:
    // TODO: why type and typeID?
    Type type_;
    string typeID_;
    string conventionsID_;
};

//! Direct yield curve segment
/*!
  A direct yield curve segment is used when the segments is entirely defined by
  a set of quotes that are passed to the constructor.

  \ingroup configuration
*/
class DirectYieldCurveSegment : public YieldCurveSegment {
public:
    //! \name Constructors/Destructors
    //@{
    //! Default constructor
    DirectYieldCurveSegment() {}
    //! Detailed constructor
    DirectYieldCurveSegment(const string& typeID, const string& conventionsID, const vector<string>& quotes);
    //! Default destructor
    virtual ~DirectYieldCurveSegment() {}
    //@}

    //! \name Serialisation
    //@{
    virtual void fromXML(XMLNode* node);
    virtual XMLNode* toXML(XMLDocument& doc);
    //@}

    //! \name Visitability
    //@{
    virtual void accept(AcyclicVisitor&);
    //@}
};

//! Simple yield curve segment
/*!
  A simple yield curve segment is used when the curve segment is determined by
  a set of quotes and a projection curve.

  \ingroup configuration
*/
class SimpleYieldCurveSegment : public YieldCurveSegment {
public:
    //! \name Constructors/Destructors
    //@{
    //! Default constructor
    SimpleYieldCurveSegment() {}
    //! Detailed constructor
    SimpleYieldCurveSegment(const string& typeID, const string& conventionsID, const vector<string>& quotes,
                            const string& projectionCurveID = string());
    //! Default destructor
    virtual ~SimpleYieldCurveSegment() {}
    //@}

    //! \name Serialisation
    //@{
    virtual void fromXML(XMLNode* node);
    virtual XMLNode* toXML(XMLDocument& doc);
    //@}

    //! \name Inspectors
    //@{
    const string& projectionCurveID() const { return projectionCurveID_; }
    //@}

    //! \name Visitability
    //@{
    virtual void accept(AcyclicVisitor&);
    //@}

private:
    string projectionCurveID_;
};

//! Avergae OIS yield curve segment
/*!
  The average OIS yield curve segment is used e.g. for USD OIS curve building where
  the curve segment is determined by  a set of composite quotes and a projection curve.
  The composite quote is  represented here as a pair of quote strings, a tenor basis spread
  and an interest rate swap quote.

  \ingroup configuration
*/
class AverageOISYieldCurveSegment : public YieldCurveSegment {
public:
    //! \name Constructors/Destructors
    //@{
    //! Default constructor
    AverageOISYieldCurveSegment() {}
    //! Detailec constructor
    AverageOISYieldCurveSegment(const string& typeID, const string& conventionsID, const vector<string>& quotes,
                                const string& projectionCurveID);
    //! Default destructor
    virtual ~AverageOISYieldCurveSegment() {}
    //@}

    //! \name Serialisation
    //@{
    virtual void fromXML(XMLNode* node);
    virtual XMLNode* toXML(XMLDocument& doc);
    //@}

    //! \name Inspectors
    //@{
    const string& projectionCurveID() const { return projectionCurveID_; }
    //@}

    //! \name Visitability
    //@{
    virtual void accept(AcyclicVisitor&);
    //@}

private:
    string projectionCurveID_;
};

//! Tenor Basis yield curve segment
/*!
  Yield curve building from tenor basis swap quotes requires a set of tenor
  basis spread quotes and the projection curve for either the shorter or the longer tenor
  which acts as the reference curve.

  \ingroup configuration
*/
class TenorBasisYieldCurveSegment : public YieldCurveSegment {
public:
    //! \name Constructors/Destructors
    //@{
    //! Default constructor
    TenorBasisYieldCurveSegment() {}
    //! Detailed constructor
    TenorBasisYieldCurveSegment(const string& typeID, const string& conventionsID, const vector<string>& quotes,
                                const string& shortProjectionCurveID, const string& longProjectionCurveID);
    //! Default destructor
    virtual ~TenorBasisYieldCurveSegment() {}
    //@}

    //!\name Serialisation
    //@{
    virtual void fromXML(XMLNode* node);
    virtual XMLNode* toXML(XMLDocument& doc);
    //@}

    //! \name Inspectors
    //@{
    const string& shortProjectionCurveID() const { return shortProjectionCurveID_; }
    const string& longProjectionCurveID() const { return longProjectionCurveID_; }
    //@}

    //! \name Visitability
    //@{
    virtual void accept(AcyclicVisitor&);
    //@}

private:
    string shortProjectionCurveID_;
    string longProjectionCurveID_;
};

//! Cross Currency yield curve segment
/*!
  Cross currency basis spread adjusted discount curves for 'domestic' currency cash flows
  are built using this segment type which requires cross currency basis spreads quotes,
  the spot FX quote ID and at least the 'foreign' discount curve ID.
  Projection curves for both currencies can be provided as well for consistency with
  tenor basis in each currency.

  \ingroup configuration
*/
class CrossCcyYieldCurveSegment : public YieldCurveSegment {
public:
    //! \name Constructors/Destructors
    //@{
    //! Default constructor
    CrossCcyYieldCurveSegment() {}
    //! Detailed constructor
    CrossCcyYieldCurveSegment(const string& typeID, const string& conventionsID, const vector<string>& quotes,
                              const string& spotRateID, const string& foreignDiscountCurveID,
                              const string& domesticProjectionCurveID = string(),
                              const string& foreignProjectionCurveID = string());
    //! Default destructor
    virtual ~CrossCcyYieldCurveSegment() {}
    //@}

    //! \name Serialisation
    //@{
    virtual void fromXML(XMLNode* node);
    virtual XMLNode* toXML(XMLDocument& doc);
    //@}

    //! \name Inspectors
    //@{
    const string& spotRateID() const { return spotRateID_; }
    const string& foreignDiscountCurveID() const { return foreignDiscountCurveID_; }
    const string& domesticProjectionCurveID() const { return domesticProjectionCurveID_; }
    const string& foreignProjectionCurveID() const { return foreignProjectionCurveID_; }
    //@}

    //! \name Visitability
    //@{
    virtual void accept(AcyclicVisitor&);
    //@}

private:
    string spotRateID_;
    string foreignDiscountCurveID_;
    string domesticProjectionCurveID_;
    string foreignProjectionCurveID_;
};

//! Zero Spreaded yield curve segment
/*!
  A zero spreaded segment is used to build a yield curve from zero spread quotes and
  a reference yield curve.

  \ingroup configuration
*/
class ZeroSpreadedYieldCurveSegment : public YieldCurveSegment {
public:
    //! \name Constructors/Destructors
    //@{
    //! Default constructor
    ZeroSpreadedYieldCurveSegment() {}
    //! Detailed constructor
    ZeroSpreadedYieldCurveSegment(const string& typeID, const string& conventionsID, const vector<string>& quotes,
                                  const string& referenceCurveID);
    //! Default destructor
    virtual ~ZeroSpreadedYieldCurveSegment() {}
    //@}

    //! \name Serialisation
    //@{
    virtual void fromXML(XMLNode* node);
    virtual XMLNode* toXML(XMLDocument& doc);
    //@}

    //! \name Inspectors
    //@{
    const string& referenceCurveID() const { return referenceCurveID_; }
    //@}

    //! \name Visitability
    //@{
    virtual void accept(AcyclicVisitor&);
    //@}

private:
    string referenceCurveID_;
};

//! Discount ratio yield curve segment
/*! Used to configure a QuantExt::DiscountRatioModifiedCurve.

    \ingroup configuration
*/
class DiscountRatioYieldCurveSegment : public YieldCurveSegment {
public:
    //! \name Constructors/Destructors
    //@{
    //! Default constructor
    DiscountRatioYieldCurveSegment() {}
    //! Detailed constructor
    DiscountRatioYieldCurveSegment(const std::string& typeId, const std::string& baseCurveId,
                                   const std::string& baseCurveCurrency, const std::string& numeratorCurveId,
                                   const std::string& numeratorCurveCurrency, const std::string& denominatorCurveId,
                                   const std::string& denominatorCurveCurrency);
    //@}

    //! \name Serialisation
    //@{
    virtual void fromXML(XMLNode* node);
    virtual XMLNode* toXML(XMLDocument& doc);
    //@}

    //! \name Inspectors
    //@{
    const string& baseCurveId() const { return baseCurveId_; }
    const string& baseCurveCurrency() const { return baseCurveCurrency_; }
    const string& numeratorCurveId() const { return numeratorCurveId_; }
    const string& numeratorCurveCurrency() const { return numeratorCurveCurrency_; }
    const string& denominatorCurveId() const { return denominatorCurveId_; }
    const string& denominatorCurveCurrency() const { return denominatorCurveCurrency_; }
    //@}

    //! \name Visitability
    //@{
    void accept(QuantLib::AcyclicVisitor& v);
    //@}

private:
    std::string baseCurveId_;
    std::string baseCurveCurrency_;
    std::string numeratorCurveId_;
    std::string numeratorCurveCurrency_;
    std::string denominatorCurveId_;
    std::string denominatorCurveCurrency_;
};

//! Yield Curve configuration
/*!
  Wrapper class containing all yield curve segments needed to build a yield curve.

  \ingroup configuration
 */
class YieldCurveConfig : public CurveConfig {
public:
    //! \name Constructors/Destructurs
    //@{
    //! Default constructor
    YieldCurveConfig() {}
    //! Detailed constructor
    YieldCurveConfig(const string& curveID, const string& curveDescription, const string& currency,
                     const string& discountCurveID, const vector<boost::shared_ptr<YieldCurveSegment>>& curveSegments,
                     const string& interpolationVariable = "Discount", const string& interpolationMethod = "LogLinear",
                     const string& zeroDayCounter = "A365", bool extrapolation = true, Real tolerance = 1.0e-12);
    //! Default destructor
    virtual ~YieldCurveConfig() {}
    //@}

    //! \name Serilalisation
    //@{
    virtual void fromXML(XMLNode* node) override;
    virtual XMLNode* toXML(XMLDocument& doc) override;
    //@}

    //! \name Inspectors
    //@{
    const string& currency() const { return currency_; }
    const string& discountCurveID() const { return discountCurveID_; }
    const vector<boost::shared_ptr<YieldCurveSegment>>& curveSegments() const { return curveSegments_; }
    const string& interpolationVariable() const { return interpolationVariable_; }
    const string& interpolationMethod() const { return interpolationMethod_; }
    const string& zeroDayCounter() const { return zeroDayCounter_; }
    bool extrapolation() const { return extrapolation_; }
    Real tolerance() const { return tolerance_; }
    const set<string>& requiredYieldCurveIDs() const { return requiredYieldCurveIDs_; }
    //@}

    //! \name Setters
    //@{
    string& interpolationVariable() { return interpolationVariable_; }
    string& interpolationMethod() { return interpolationMethod_; }
    string& zeroDayCounter() { return zeroDayCounter_; }
    bool& extrapolation() { return extrapolation_; }
    Real& tolerance() { return tolerance_; }
    //@}

    const vector<string>& quotes() override;

private:
    void populateRequiredYieldCurveIDs();

    // Mandatory members
    string currency_;
    string discountCurveID_;
    vector<boost::shared_ptr<YieldCurveSegment>> curveSegments_;
    set<string> requiredYieldCurveIDs_;

    // Optional members
    string interpolationVariable_;
    string interpolationMethod_;
    string zeroDayCounter_;
    bool extrapolation_;
    Real tolerance_;
};

// Map form curveID to YieldCurveConfig
using YieldCurveConfigMap = std::map<string, boost::shared_ptr<YieldCurveConfig>>;
} // namespace data
} // namespace ore


// This file is part of the dune-stuff project:
//   https://github.com/wwu-numerik/dune-stuff/
// Copyright holders: Rene Milk, Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)
//
// Contributors: Tobias Leibner

#ifndef DUNE_STUFF_LA_CONTAINER_VECTOR_INTERFACE_HH
#define DUNE_STUFF_LA_CONTAINER_VECTOR_INTERFACE_HH

#include <cmath>
#include <limits>
#include <iostream>
#include <vector>
#include <complex>

#include <boost/numeric/conversion/cast.hpp>

#include <dune/common/ftraits.hh>

#include <dune/stuff/common/crtp.hh>
#include <dune/stuff/common/exceptions.hh>
#include <dune/stuff/common/float_cmp.hh>
#include <dune/stuff/common/type_utils.hh>
#include <dune/stuff/common/vector.hh>
#include <dune/stuff/common/math.hh>

#include "container-interface.hh"
#include "vector-interface-internal.hh"

namespace Dune {
namespace Stuff {
namespace LA {

/**
 *  \brief  Contains tags mostly needed for python bindings.
 */
namespace Tags {

class VectorInterface
{
};

} // namespace Tags

template <class Traits, class ScalarImp = typename Traits::ScalarType>
class VectorInterface : public ContainerInterface<Traits, ScalarImp>, public Tags::VectorInterface
{
public:
  typedef typename Traits::derived_type derived_type;
  typedef typename Dune::FieldTraits<ScalarImp>::field_type ScalarType;
  typedef typename Dune::FieldTraits<ScalarImp>::real_type RealType;

  typedef internal::VectorInputIterator<Traits, ScalarType> const_iterator;
  typedef internal::VectorOutputIterator<Traits, ScalarType> iterator;

  static_assert(std::is_same<ScalarType, typename Traits::ScalarType>::value, "");

  virtual ~VectorInterface() {}

  /// \name Have to be implemented by a derived class in addition to the ones required by ContainerInterface!
  /// \{

  /**
   * \brief   The size of the vector.
   * \return  The size of the vector.
   */
  inline size_t size() const
  {
    CHECK_CRTP(this->as_imp().size());
    return this->as_imp().size();
  }

  /**
   * \brief Add a scalar to the iith entry.
   */
  inline void add_to_entry(const size_t ii, const ScalarType& value)
  {
    CHECK_AND_CALL_CRTP(this->as_imp().add_to_entry(ii, value));
  }

  /**
   * \brief Set the iith entry to given scalar.
   */
  inline void set_entry(const size_t ii, const ScalarType& value)
  {
    CHECK_AND_CALL_CRTP(this->as_imp().set_entry(ii, value));
  }

  /**
   * \brief Get the iith entry.
   * \todo  Default implement using get_entry_ref!
   */
  inline ScalarType get_entry(const size_t ii) const
  {
    CHECK_CRTP(this->as_imp().get_entry(ii));
    return this->as_imp().get_entry(ii);
  }

  inline ScalarType& get_entry_ref(const size_t ii)
  {
    CHECK_CRTP(this->as_imp().get_entry_ref(ii));
    return this->as_imp().get_entry_ref(ii);
  }

  inline const ScalarType& get_entry_ref(const size_t ii) const
  {
    CHECK_CRTP(this->as_imp().get_entry_ref(ii));
    return this->as_imp().get_entry_ref(ii);
  }

  /// \}
  /// \name Provided by the interface for convenience!
  /// \note Those marked as virtual may be implemented more efficiently in a derived class!
  /// \{

  virtual void set_all(const ScalarType& val)
  {
    for (auto& element : *this)
      element = val;
  }

  virtual bool valid() const
  {
    for (const auto& val : *this) {
      if (Common::isnan(val) || Common::isinf(val))
        return false;
    }
    return true;
  } // ... valid()

  /**
   * \brief Get writable reference to the iith entry.
   */
  inline ScalarType& operator[](const size_t ii) { return get_entry_ref(ii); }

  /**
   * \brief Get read-only reference to the iith entry.
   */
  inline const ScalarType& operator[](const size_t ii) const { return get_entry_ref(ii); }

  /**
   * \brief   The dimension of the vector.
   * \return  The dimension of the vector.
   * \see     size()
   */
  inline size_t dim() const { return size(); }

  virtual ScalarType mean() const
  {
    ScalarType ret = 0.0;
    for (const auto& element : *this)
      ret += element;
    ret /= size();
    return ret;
  } // ... mean()

  /**
   *  \brief  The maximum absolute value of the vector.
   *  \return A pair of the lowest index at which the maximum is attained and the absolute maximum value.
   *  \note   If you override this method please use exceptions instead of assertions (for the python bindings).
   */
  virtual std::pair<size_t, RealType> amax() const
  {
    auto result = std::make_pair(size_t(0), RealType(0));
    for (size_t ii = 0; ii < size(); ++ii) {
      const auto value = std::abs(get_entry_ref(ii));
      if (value > result.second) {
        result.first  = ii;
        result.second = value;
      }
    }
    return result;
  } // ... amax(...)

  /**
   *  \brief  Check vectors for equality.
   *          Equality of two vectors is defined as in Dune::FloatCmp componentwise.
   *  \param  other   A vector of same dimension to compare with.
   *  \param  epsilon See Dune::FloatCmp.
   *  \return Truth value of the comparison.
   *  \see    Dune::Stuff::Common::FloatCmp
   *  \note   If you override this method please use exceptions instead of assertions (for the python bindings).
   */
  virtual bool
      almost_equal(const derived_type& other,
                   const ScalarType epsilon = Stuff::Common::FloatCmp::DefaultEpsilon<ScalarType>::value()) const
  {
    if (other.size() != size())
      DUNE_THROW(Exceptions::shapes_do_not_match,
                 "The size of other (" << other.size() << ") does not match the size of this (" << size() << ")!");
    return Stuff::Common::FloatCmp::eq(this->as_imp(), other, epsilon);
  } // ... almost_equal(...)

  /**
   *  \brief  Check vectors for equality (variant for arbitrary derived combinations).
   *          Equality of two vectors is defined as in Dune::FloatCmp componentwise.
   *  \param  other   A vector of same dimension to compare with.
   *  \param  epsilon See Dune::FloatCmp.
   *  \return Truth value of the comparison.
   *  \see    Dune::Stuff::Common::FloatCmp
   */
  template <class T>
  bool almost_equal(const VectorInterface<T>& other,
                    const ScalarType epsilon = Stuff::Common::FloatCmp::DefaultEpsilon<ScalarType>::value()) const
  {
    if (other.size() != size())
      DUNE_THROW(Exceptions::shapes_do_not_match,
                 "The size of other (" << other.size() << ") does not match the size of this (" << size() << ")!");
    return Stuff::Common::FloatCmp::eq(this->as_imp(), other.as_imp(), epsilon);
  } // ... almost_equal(...)

  /**
   *  \brief  Computes the scalar products between two vectors.
   *  \param  other The second factor.
   *  \return The scalar product.
   *  \note   If you override this method please use exceptions instead of assertions (for the python bindings).
   */
  virtual ScalarType dot(const derived_type& other) const
  {
    if (other.size() != size())
      DUNE_THROW(Exceptions::shapes_do_not_match,
                 "The size of other (" << other.size() << ") does not match the size of this (" << size() << ")!");
    ScalarType result = 0;
    for (size_t ii = 0; ii < size(); ++ii)
      result += std::conj(get_entry_ref(ii)) * other.get_entry_ref(ii);
    return result;
  } // ... dot(...)

  /**
   *  \brief  The l1-norm of the vector.
   *  \return The l1-norm of the vector.
   *  \note   If you override this method please use exceptions instead of assertions (for the python bindings).
   */
  virtual RealType l1_norm() const
  {
    RealType result = 0;
    for (size_t ii = 0; ii < size(); ++ii)
      result += std::abs(get_entry_ref(ii));
    return result;
  } // ... l1_norm(...)

  /**
   *  \brief  The l2-norm of the vector.
   *  \return The l2-norm of the vector.
   *  \note   If you override this method please use exceptions instead of assertions (for the python bindings).
   */
  virtual RealType l2_norm() const
  {
    return std::sqrt(std::abs(dot(this->as_imp(*this)))); // std::abs is only needed for the right return type:
    // v.dot(v) should always be a ScalarType with zero imaginary part
  }

  /**
   *  \brief  The l-infintiy-norm of the vector.
   *  \return The l-infintiy-norm of the vector.
   *  \note   If you override this method please use exceptions instead of assertions (for the python bindings).
   */
  virtual RealType sup_norm() const { return amax().second; }

  virtual ScalarType standard_deviation() const
  {
    const ScalarType mu = mean();
    ScalarType sigma = 0.0;
    for (const auto& x_i : *this)
      sigma += std::pow(x_i - mu, 2);
    sigma /= size();
    return std::sqrt(sigma);
  } // ... standard_deviation(...)

  /**
   *  \brief  Adds two vectors.
   *  \param  other   The right summand.
   *  \param  result  Vector to write the result of this + other to
   *  \note   If you override this method please use exceptions instead of assertions (for the python bindings).
   *  \note   If you are looking for the old (now deprecated) add() method, \see add_to_entry().
   */
  virtual void add(const derived_type& other, derived_type& result) const
  {
    if (other.size() != size())
      DUNE_THROW(Exceptions::shapes_do_not_match,
                 "The size of other (" << other.size() << ") does not match the size of this (" << size() << ")!");
    if (result.size() != size())
      DUNE_THROW(Exceptions::shapes_do_not_match,
                 "The size of result (" << result.size() << ") does not match the size of this (" << size() << ")!");
    for (size_t ii = 0; ii < size(); ++ii)
      result.set_entry(ii, get_entry_ref(ii) + other.get_entry_ref(ii));
  } // ... add(...)

  /**
   *  \brief  Adds two vectors.
   *  \param  other The right summand.
   *  \return The sum of this and other.
   *  \note   If you override this method please use exceptions instead of assertions (for the python bindings).
   *  \note   If you are looking for the old (now deprecated) add() method, \see add_to_entry().
   */
  virtual derived_type add(const derived_type& other) const
  {
    derived_type result = this->copy();
    result.iadd(other);
    return result;
  } // ... add(...)

  /**
   *  \brief  Inplace variant of add().
   *  \param  other The right summand.
   *  \note   If you override this method please use exceptions instead of assertions (for the python bindings).
   */
  virtual void iadd(const derived_type& other)
  {
    if (other.size() != size())
      DUNE_THROW(Exceptions::shapes_do_not_match,
                 "The size of other (" << other.size() << ") does not match the size of this (" << size() << ")!");
    for (size_t ii = 0; ii < size(); ++ii)
      set_entry(ii, get_entry_ref(ii) + other.get_entry_ref(ii));
  } // ... iadd(...)

  /**
   *  \brief  Subtracts two vectors.
   *  \param  other   The subtrahend.
   *  \param  result  The vectror to write the difference between this and other to.
   *  \note   If you override this method please use exceptions instead of assertions (for the python bindings).
   */
  virtual void sub(const derived_type& other, derived_type& result) const
  {
    if (other.size() != size())
      DUNE_THROW(Exceptions::shapes_do_not_match,
                 "The size of other (" << other.size() << ") does not match the size of this (" << size() << ")!");
    if (result.size() != size())
      DUNE_THROW(Exceptions::shapes_do_not_match,
                 "The size of result (" << result.size() << ") does not match the size of this (" << size() << ")!");
    for (size_t ii = 0; ii < size(); ++ii)
      result.set_entry(ii, get_entry_ref(ii) - other.get_entry_ref(ii));
  } // ... sub(...)

  /**
   *  \brief  Subtracts two vectors.
   *  \param  other The subtrahend.
   *  \return The difference between this and other.
   *  \note   If you override this method please use exceptions instead of assertions (for the python bindings).
   */
  virtual derived_type sub(const derived_type& other) const
  {
    derived_type result = this->copy();
    result.isub(other);
    return result;
  } // ... sub(...)

  /**
   *  \brief  Inplace variant of sub().
   *  \param  other The subtrahend.
   *  \note   If you override this method please use exceptions instead of assertions (for the python bindings).
   */
  virtual void isub(const derived_type& other)
  {
    if (other.size() != size())
      DUNE_THROW(Exceptions::shapes_do_not_match,
                 "The size of other (" << other.size() << ") does not match the size of this (" << size() << ")!");
    for (size_t ii = 0; ii < size(); ++ii)
      set_entry(ii, get_entry_ref(ii) - other.get_entry_ref(ii));
  } // ... isub(...)

  /**
   *  \brief  Multiplies every component of this by a scalar.
   *  \param  alpha The scalar.
   *  \return The scaled copy of this.
   */
  virtual derived_type operator*(const ScalarType& alpha)
  {
    derived_type ret = this->copy();
    ret *= alpha;
    return ret;
  } // ... operator*() ...

  /**
   *  \brief  Computes the scalar products between this and another vector.
   *  \param  other The second factor.
   *  \return The scalar product.
   *  \see dot()
   */
  virtual ScalarType operator*(const derived_type& other) { return dot(other); }

  /**
   *  \brief  Adds another vector to this, in-place variant.
   *  \param  other The second summand.
   *  \return The sum of this and other.
   */
  virtual derived_type& operator+=(const derived_type& other)
  {
    iadd(other);
    return this->as_imp(*this);
  }

  /**
   *  \brief  Subtracts another vector from this, in-place variant.
   *  \param  other The subtrahend.
   *  \return The difference between this and other.
   */
  virtual derived_type& operator-=(const derived_type& other)
  {
    isub(other);
    return this->as_imp(*this);
  }

  /**
   *  \brief  Adds two vectors.
   *  \param  other The second summand.
   *  \return The sum of the two vectors.
   */
  virtual derived_type operator+(const derived_type& other) const { return add(other); }

  /**
   *  \brief  Substracts two vectors.
   *  \param  other The subtrahend
   *  \return The difference.
   */
  virtual derived_type operator-(const derived_type& other) const { return sub(other); }

  virtual derived_type& operator+=(const ScalarType& scalar)
  {
    for (auto& element : *this)
      element += scalar;
    return this->as_imp(*this);
  }

  virtual derived_type& operator-=(const ScalarType& scalar)
  {
    for (auto& element : *this)
      element -= scalar;
    return this->as_imp(*this);
  }

  virtual derived_type& operator/=(const ScalarType& scalar)
  {
    for (auto& element : *this)
      element /= scalar;
    return this->as_imp(*this);
  }

  /**
   *  \brief  Check vectors for equality (componentwise) using almost_equal()
   *  \param  other   A vector of same dimension to compare with.
   *  \return Truth value of the comparison.
   *  \see    almost_equal()
   */
  virtual bool operator==(const derived_type& other) const { return almost_equal(other); }

  /**
   *  \brief  Check vectors for inequality using !almost_equal()
   *  \param  other   A vector of same dimension to compare with.
   *  \return Truth value of the comparison.
   */
  virtual bool operator!=(const derived_type& other) const { return !(this->operator==(other)); }

  /// \}
  /// \name Necesarry for the python bindings.
  /// \{

  /**
   * \brief Variant of dim() needed for the python bindings.
   * \see   dim()
   */
  inline DUNE_STUFF_SSIZE_T pb_dim() const
  {
    try {
      return boost::numeric_cast<DUNE_STUFF_SSIZE_T>(dim());
    } catch (boost::bad_numeric_cast& ee) {
      DUNE_THROW(Exceptions::external_error,
                 "There was an error in boost converting '" << dim() << "' to '"
                                                            << Common::Typename<ScalarType>::value()
                                                            << "': "
                                                            << ee.what());
    }
  } // ... pb_dim(...)

  /**
   * \brief Variant of add_to_entry() needed for the python bindings.
   * \see   add_to_entry()
   */
  inline void pb_add_to_entry(const DUNE_STUFF_SSIZE_T ii, const ScalarType& value)
  {
    try {
      add_to_entry(boost::numeric_cast<size_t>(ii), value);
    } catch (boost::bad_numeric_cast& ee) {
      DUNE_THROW(Exceptions::external_error,
                 "There was an error in boost converting '" << ii << "' to '" << Common::Typename<size_t>::value()
                                                            << "': "
                                                            << ee.what());
    }
  } // ... pb_add_to_entry(...)

  /**
   * \brief Variant of set_entry() needed for the python bindings.
   * \see   set_entry()
   */
  inline void pb_set_entry(const DUNE_STUFF_SSIZE_T ii, const ScalarType& value)
  {
    try {
      set_entry(boost::numeric_cast<size_t>(ii), value);
    } catch (boost::bad_numeric_cast& ee) {
      DUNE_THROW(Exceptions::external_error,
                 "There was an error in boost converting '" << ii << "' to '" << Common::Typename<size_t>::value()
                                                            << "': "
                                                            << ee.what());
    }
  } // ... pb_set_entry(...)

  /**
   * \brief Variant of get_entry() needed for the python bindings.
   * \see   get_entry()
   */
  inline ScalarType pb_get_entry(const DUNE_STUFF_SSIZE_T ii)
  {
    try {
      return get_entry(boost::numeric_cast<size_t>(ii));
    } catch (boost::bad_numeric_cast& ee) {
      DUNE_THROW(Exceptions::external_error,
                 "There was an error in boost converting '" << ii << "' to '" << Common::Typename<size_t>::value()
                                                            << "': "
                                                            << ee.what());
    }
  } // ... pb_get_entry(...)

  /**
   * \brief Variant of amax() needed for the python bindings.
   * \see   amax()
   */
  std::vector<RealType> pb_amax() const
  {
    const auto max = amax();
    try {
      return {boost::numeric_cast<RealType>(max.first), max.second};
    } catch (boost::bad_numeric_cast& ee) {
      DUNE_THROW(Exceptions::external_error,
                 "There was an error in boost converting '" << max.first << "' to '"
                                                            << Common::Typename<RealType>::value()
                                                            << "': "
                                                            << ee.what());
    }
  } // ... pb_amax(...)

  std::vector<ScalarType> components(const std::vector<DUNE_STUFF_SSIZE_T>& component_indices) const
  {
    if (component_indices.size() > dim())
      DUNE_THROW(Exceptions::index_out_of_range,
                 "size of component_indices (" << component_indices.size() << ") is larger than the dim of this ("
                                               << dim()
                                               << ")!");
    std::vector<ScalarType> values(component_indices.size(), ScalarType(0));
    try {
      for (size_t ii = 0; ii < component_indices.size(); ++ii) {
        const size_t component = boost::numeric_cast<size_t>(component_indices[ii]);
        if (component >= dim())
          DUNE_THROW(Exceptions::index_out_of_range,
                     "component_indices[" << ii << "] is too large for this (" << dim() << ")!");
        values[ii] = get_entry(component);
      }
    } catch (boost::bad_numeric_cast& ee) {
      DUNE_THROW(Exceptions::external_error, "There was an error in boost during a numeric_cast: " << ee.what());
    }
    return values;
  } // components(...)

  /// \}

  iterator begin() { return iterator(*this); }

  const_iterator begin() const { return const_iterator(*this); }

  iterator end() { return iterator(*this, true); }

  const_iterator end() const { return const_iterator(*this, true); }

  operator std::vector<ScalarType>() const
  {
    std::vector<ScalarType> ret(dim());
    for (size_t ii = 0; ii < dim(); ++ii)
      ret[ii] = this->operator[](ii);
    return ret;
  }

private:
  template <class T, class S>
  friend std::ostream& operator<<(std::ostream& /*out*/, const VectorInterface<T, S>& /*vector*/);
}; // class VectorInterface

namespace internal {

template <class V>
struct is_vector_helper
{
  DSC_has_typedef_initialize_once(Traits) DSC_has_typedef_initialize_once(ScalarType)

      static const bool is_candidate = DSC_has_typedef(Traits)<V>::value && DSC_has_typedef(ScalarType)<V>::value;
}; // class is_vector_helper

} // namespace internal

template <class V, bool candidate = internal::is_vector_helper<V>::is_candidate>
struct is_vector : public std::is_base_of<VectorInterface<typename V::Traits, typename V::ScalarType>, V>
{
};

template <class V>
struct is_vector<V, false> : public std::false_type
{
};

namespace internal {

template <class VectorImp>
struct VectorAbstractionBase
{
  static const bool is_vector = LA::is_vector<VectorImp>::value;

  static const bool has_static_size = false;

  static const size_t static_size = std::numeric_limits<size_t>::max();

  typedef typename std::conditional<is_vector, VectorImp, void>::type VectorType;
  typedef typename std::conditional<is_vector, typename VectorImp::ScalarType, void>::type ScalarType;
  typedef typename std::conditional<is_vector, typename VectorImp::RealType, void>::type RealType;
  typedef ScalarType S;
  typedef RealType R;

  static inline typename std::enable_if<is_vector, VectorType>::type create(const size_t sz) { return VectorType(sz); }

  static inline typename std::enable_if<is_vector, VectorType>::type create(const size_t sz, const ScalarType& val)
  {
    return VectorType(sz, val);
  }
}; // struct VectorAbstractionBase

} // namespace internal

template <class T, class S>
std::ostream& operator<<(std::ostream& out, const VectorInterface<T, S>& vector)
{
  out << "[";
  const size_t sz = vector.size();
  if (sz > 0) {
    out << vector[0];
    for (size_t ii = 1; ii < sz; ++ii)
      out << "\n " << vector[ii];
  } else
    out << " ";
  out << "]";
  return out;
} // ... operator<<(...)

} // namespace LA
} // namespace Stuff
} // namespace Dune

#endif // DUNE_STUFF_LA_CONTAINER_VECTOR_INTERFACE_HH