text:
/**
 * \file   MeshSurfaceExtraction.cpp
 * \author Karsten Rink
 * \date   2013-04-04
 * \brief  Implementation of the MeshSurfaceExtraction class.
 *
 * \copyright
 * Copyright (c) 2012-2017, OpenGeoSys Community (http://www.opengeosys.org)
 *            Distributed under a Modified BSD License.
 *              See accompanying file LICENSE.txt or
 *              http://www.opengeosys.org/project/license
 *
 */

#include "MeshSurfaceExtraction.h"

#include <memory>

#include <boost/math/constants/constants.hpp>

#include <logog/include/logog.hpp>

#include "MeshLib/Mesh.h"
#include "MeshLib/Elements/Line.h"
#include "MeshLib/Elements/Tri.h"
#include "MeshLib/Elements/Quad.h"
#include "MeshLib/MeshEditing/DuplicateMeshComponents.h"
#include "MeshLib/MeshSearch/NodeSearch.h"
#include "MeshLib/MeshEditing/RemoveMeshComponents.h"

namespace MeshLib {

std::vector<double> MeshSurfaceExtraction::getSurfaceAreaForNodes(const MeshLib::Mesh &mesh)
{
    std::vector<double> node_area_vec;
    if (mesh.getDimension() != 2)
    {
        ERR ("Error in MeshSurfaceExtraction::getSurfaceAreaForNodes() - Given mesh is no surface mesh (dimension != 2).");
        return node_area_vec;
    }

    double total_area (0);

    // for each node, a vector containing all the element idget every element
    const std::vector<MeshLib::Node*> &nodes = mesh.getNodes();
    const std::size_t nNodes ( mesh.getNumberOfNodes() );
    for (std::size_t n=0; n<nNodes; ++n)
    {
        double node_area (0);

        std::vector<MeshLib::Element*> conn_elems = nodes[n]->getElements();
        const std::size_t nConnElems (conn_elems.size());

        for (std::size_t i=0; i<nConnElems; ++i)
        {
            const MeshLib::Element* elem (conn_elems[i]);
            const unsigned nElemParts = (elem->getGeomType() == MeshElemType::TRIANGLE) ? 3 : 4;
            const double area = conn_elems[i]->getContent() / nElemParts;
            node_area += area;
            total_area += area;
        }

        node_area_vec.push_back(node_area);
    }

    INFO ("Total surface Area: %f", total_area);

    return node_area_vec;
}

MeshLib::Mesh* MeshSurfaceExtraction::getMeshSurface(
    const MeshLib::Mesh& subsfc_mesh, const MathLib::Vector3& dir, double angle,
    std::string const& subsfc_node_id_prop_name,
    std::string const& subsfc_element_id_prop_name,
    std::string const& face_id_prop_name)
{
    // allow slightly greater angles than 90 degrees for numerical errors
    if (angle < 0 || angle > 91)
    {
        ERR ("Supported angle between 0 and 90 degrees only.");
        return nullptr;
    }

    INFO ("Extracting mesh surface...");
    std::vector<MeshLib::Element*> sfc_elements;
    std::vector<std::size_t> element_ids_map;
    std::vector<std::size_t> face_ids_map;
    get2DSurfaceElements(subsfc_mesh.getElements(), sfc_elements,
                         element_ids_map, face_ids_map, dir, angle,
                         subsfc_mesh.getDimension());

    if (sfc_elements.empty())
        return nullptr;

    std::vector<MeshLib::Node*> sfc_nodes;
    std::vector<std::size_t> node_id_map(subsfc_mesh.getNumberOfNodes());
    get2DSurfaceNodes(sfc_nodes, subsfc_mesh.getNumberOfNodes(), sfc_elements,
                      node_id_map);

    // create new elements vector with newly created nodes
    std::vector<MeshLib::Element*> new_elements;
    new_elements.reserve(sfc_elements.size());
    for (auto elem = sfc_elements.cbegin(); elem != sfc_elements.cend(); ++elem)
    {
        unsigned const n_elem_nodes ((*elem)->getNumberOfBaseNodes());
        MeshLib::Node** new_nodes = new MeshLib::Node*[n_elem_nodes];
        for (unsigned k(0); k<n_elem_nodes; k++)
            new_nodes[k] = sfc_nodes[node_id_map[(*elem)->getNode(k)->getID()]];
        if ((*elem)->getGeomType() == MeshElemType::TRIANGLE)
            new_elements.push_back(new MeshLib::Tri(new_nodes));
        else {
            assert((*elem)->getGeomType() == MeshElemType::QUAD);
            new_elements.push_back(new MeshLib::Quad(new_nodes));
        }
        delete *elem;
    }

    std::vector<std::size_t> id_map;
    if (!subsfc_node_id_prop_name.empty())
    {
        id_map.reserve(sfc_nodes.size());
        for (auto const* node : sfc_nodes)
            id_map.push_back(node->getID());
    }
    MeshLib::Mesh* result(
        new Mesh(subsfc_mesh.getName() + "-Surface", sfc_nodes, new_elements));

    // transmit the original node ids of the subsurface mesh as a property
    if (!subsfc_node_id_prop_name.empty())
    {
        MeshLib::addPropertyToMesh(*result, subsfc_node_id_prop_name,
                                   MeshLib::MeshItemType::Node, 1, id_map);
    }

    // transmit the original subsurface element ids as a property
    if (!subsfc_element_id_prop_name.empty()) {
        MeshLib::addPropertyToMesh(*result, subsfc_element_id_prop_name,
                                   MeshLib::MeshItemType::Cell, 1,
                                   element_ids_map);
    }

    // transmit the face id of the original subsurface element as a property
    if (!face_id_prop_name.empty()) {
        MeshLib::addPropertyToMesh(*result, face_id_prop_name,
                                   MeshLib::MeshItemType::Cell, 1,
                                   face_ids_map);
    }

    return result;
}

MeshLib::Mesh* MeshSurfaceExtraction::getMeshBoundary(const MeshLib::Mesh &mesh)
{
    if (mesh.getDimension()==1)
        return nullptr;

    // For 3D meshes return the 2D surface
    if (mesh.getDimension()==3)
    {
        MathLib::Vector3 dir(0,0,0);
        return getMeshSurface(mesh, dir, 90);
    }

    // For 2D meshes return the boundary lines
    std::vector<MeshLib::Node*> nodes = MeshLib::copyNodeVector(mesh.getNodes());
    std::vector<MeshLib::Element*> boundary_elements;

    std::vector<MeshLib::Element*> const& org_elems (mesh.getElements());
    for (auto it=org_elems.begin(); it!=org_elems.end(); ++it)
    {
        MeshLib::Element* elem (*it);
        std::size_t const n_edges (elem->getNumberOfEdges());
        for (std::size_t i=0; i<n_edges; ++i)
            if (elem->getNeighbor(i) == nullptr)
            {
                MeshLib::Element const*const edge (elem->getEdge(i));
                boundary_elements.push_back(MeshLib::copyElement(edge, nodes));
                delete edge;
            }
    }
    MeshLib::Mesh* result = new MeshLib::Mesh("Boundary Mesh", nodes, boundary_elements);
    MeshLib::NodeSearch ns(*result);
    if (ns.searchUnused() == 0) {
        return result;
    } else {
        auto removed = MeshLib::removeNodes(*result, ns.getSearchedNodeIDs(), result->getName());
        delete result;
        return removed;
    }
}

void MeshSurfaceExtraction::get2DSurfaceElements(
    const std::vector<MeshLib::Element*>& all_elements,
    std::vector<MeshLib::Element*>& sfc_elements,
    std::vector<std::size_t>& element_to_bulk_element_id_map,
    std::vector<std::size_t>& element_to_bulk_face_id_map,
    const MathLib::Vector3& dir, double angle, unsigned mesh_dimension)
{
    if (mesh_dimension < 2 || mesh_dimension > 3)
        ERR("Cannot handle meshes of dimension %i", mesh_dimension);

    bool const complete_surface = (MathLib::scalarProduct(dir, dir) == 0);

    double const pi(boost::math::constants::pi<double>());
    double const cos_theta(std::cos(angle * pi / 180.0));
    MathLib::Vector3 const norm_dir(dir.getNormalizedVector());

    for (auto const* elem : all_elements)
    {
        const unsigned element_dimension(elem->getDimension());
        if (element_dimension < mesh_dimension)
            continue;

        if (element_dimension == 2)
        {
            if (!complete_surface)
            {
                auto const* face = elem;
                if (MathLib::scalarProduct(
                        FaceRule::getSurfaceNormal(face).getNormalizedVector(),
                        norm_dir) > cos_theta)
                    continue;
            }
            sfc_elements.push_back(elem->clone());
            element_to_bulk_element_id_map.push_back(elem->getID());
            element_to_bulk_face_id_map.push_back(0);
        }
        else
        {
            if (!elem->isBoundaryElement())
                continue;
            const unsigned nFaces(elem->getNumberOfFaces());
            for (unsigned j = 0; j < nFaces; ++j)
            {
                if (elem->getNeighbor(j) != nullptr)
                    continue;

                auto const face =
                    std::unique_ptr<MeshLib::Element const>{elem->getFace(j)};
                if (!complete_surface)
                {
                    if (MathLib::scalarProduct(
                            FaceRule::getSurfaceNormal(face.get())
                                .getNormalizedVector(),
                            norm_dir) < cos_theta)
                    {
                        continue;
                    }
                }
                if (face->getGeomType() == MeshElemType::TRIANGLE)
                    sfc_elements.push_back(new MeshLib::Tri(
                        *static_cast<const MeshLib::Tri*>(face.get())));
                else
                    sfc_elements.push_back(new MeshLib::Quad(
                        *static_cast<const MeshLib::Quad*>(face.get())));
                element_to_bulk_element_id_map.push_back(elem->getID());
                element_to_bulk_face_id_map.push_back(j);
            }
        }
    }
}

void MeshSurfaceExtraction::get2DSurfaceNodes(
    std::vector<MeshLib::Node*>& sfc_nodes, std::size_t n_all_nodes,
    const std::vector<MeshLib::Element*>& sfc_elements,
    std::vector<std::size_t>& node_id_map)
{
    std::vector<const MeshLib::Node*> tmp_nodes(n_all_nodes, nullptr);
    for (auto const* elem : sfc_elements)
    {
        for (unsigned j = 0; j < elem->getNumberOfBaseNodes(); ++j)
        {
            const MeshLib::Node* node(elem->getNode(j));
            tmp_nodes[node->getID()] = node;
        }
    }
    const std::size_t nNodes(tmp_nodes.size());
    for (unsigned i = 0; i < nNodes; ++i)
    {
        if (tmp_nodes[i])
        {
            node_id_map[i] = sfc_nodes.size();
            sfc_nodes.push_back(new MeshLib::Node(*tmp_nodes[i]));
        }
    }
}

std::vector<MeshLib::Node*> MeshSurfaceExtraction::getSurfaceNodes(
    const MeshLib::Mesh& mesh, const MathLib::Vector3& dir, double angle)
{
    INFO ("Extracting surface nodes...");
    std::vector<MeshLib::Element*> sfc_elements;
    std::vector<std::size_t> element_to_bulk_element_id_map;
    std::vector<std::size_t> element_to_bulk_face_id_map;
    get2DSurfaceElements(
        mesh.getElements(), sfc_elements, element_to_bulk_element_id_map,
        element_to_bulk_face_id_map, dir, angle, mesh.getDimension());

    std::vector<MeshLib::Node*> sfc_nodes;
    std::vector<std::size_t> node_id_map(mesh.getNumberOfNodes());
    get2DSurfaceNodes(sfc_nodes, mesh.getNumberOfNodes(), sfc_elements,
                      node_id_map);

    for (auto e : sfc_elements)
        delete e;

    return sfc_nodes;
}

} // end namespace MeshLib


text:
#include <boost/lexical_cast.hpp>
#include <boost/uuid/random_generator.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/algorithm/string/join.hpp>
#include <boost/date_time/local_time/local_time.hpp>
#include <boost/locale/encoding.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/device/file.hpp>
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include <map>

#include "tinyxml/tinyxml.h"

#include "Mesh.hpp"
#include "MeshLibrary.hpp"
#include "MaterialLibrary.hpp"
#include "Scene.hpp"
#include "Material.hpp"
#include "Node.hpp"
#include "Triangles.hpp"
#include "Polygons.hpp"
#include "ImageLibrary.hpp"
#include "Image.hpp"
#include "NCName.hpp"
#include "wrapio.hpp"
#include "NodeLibrary.hpp"
#include "all.hpp"

#include "Writer.hpp"

using namespace boost::property_tree;

namespace col
{
	const std::string XMLNS = "http://www.collada.org/2005/11/COLLADASchema";
	const std::string VERSION = "1.4.1";
    const std::string SCHEMA_LOCATION = "http://www.khronos.org/files/collada_schema_1_4";

    template <typename T>
    std::string complexJoin(const std::vector<T>& container, const std::string& delimiter)
    {
        std::stringstream temp;

        size_t i = 1;

        for (std::vector<T>::const_iterator it = container.begin(); it != container.end(); ++it)
        {
            if (it != container.begin())
            {
                temp << delimiter;
            }

            temp << boost::lexical_cast<std::string>(*it);

            if ((i % 10) == 0)
            {
                //temp << std::endl;
            }

            ++i;
        }

        return temp.str();
    }

    std::string createGeometryId(const MeshPtr& mesh)
    {
        return mesh->getId() + "-geometry";
    }

    std::string createPositionsArrayId(const MeshPtr& mesh)
    {
        return mesh->getId() + "-positions-array";
    }

    std::string createNormalsArrayId(const MeshPtr& mesh)
    {
        return mesh->getId() + "-normals-array";
    }

    std::string createTextureCoordinatesArrayId(const MeshPtr& mesh)
    {
        return mesh->getId() + "-textureCoordinates-array";
    }

    std::string createPositionsId(const MeshPtr& mesh)
    {
        return mesh->getId() + "-positions";
    }

    std::string createNormalsId(const MeshPtr& mesh)
    {
        return mesh->getId() + "-normals";
    }

    std::string createTextureCoordinatesId(const MeshPtr& mesh)
    {
        return mesh->getId() + "-textureCoordinates";
    }

    std::string createVerticesId(const MeshPtr& mesh)
    {
        return mesh->getId() + "-vertices";
    }

    std::string createTextureSamplerId(const TexturePtr& texture)
    {
        return texture->getId() + "-sampler";
    }

    std::string createTextureSurfaceId(const TexturePtr& texture)
    {
        return texture->getId() + "-surface";
    }

    std::string createMaterialReference(const MaterialPtr& material)
    {
        return material->getId() + "-ref";
    }

    std::string createMaterialReference(const PrimitivePtr& primitive)
    {
        MaterialPtr material = primitive->getMaterial().lock();
        return createMaterialReference(material);
    }

    void writeH(const Indices& indices, TiXmlElement* parentXml)
    {
        assert(indices.size() >= 3);

        TiXmlElement* hXml = new TiXmlElement("h");
        parentXml->LinkEndChild(hXml);

        std::string hStr = complexJoin(indices, " ");

        TiXmlText* hText = new TiXmlText(hStr);
        hXml->LinkEndChild(hText);
    }

    void writeP(const Indices& indices, TiXmlElement* trianglesXml)
    {
        assert(indices.size() >= 3);

        TiXmlElement* pXml = new TiXmlElement("p");
        trianglesXml->LinkEndChild(pXml);

        std::string pStr = complexJoin(indices, " ");

        TiXmlText* pText = new TiXmlText(pStr);
        pXml->LinkEndChild(pText);
    }

    std::string createDateTime()
    {
        using namespace boost::local_time;

        std::stringstream temp;
        time_zone_ptr tz;
        local_date_time now = local_sec_clock().local_time(tz);
        local_time_facet* o = new local_time_facet();
        temp.imbue(std::locale(std::locale::classic(), o));
        o->format("%Y-%m-%dT%H:%M:%S%Q");
        temp << now;

        return temp.str();
    }

	void writeAsset(TiXmlElement* colladaXml)
	{
		TiXmlElement* assetXml = new TiXmlElement("asset");
		colladaXml->LinkEndChild(assetXml);

		// 2006-08-23T22:29:59Z
		TiXmlElement* createXml = new TiXmlElement("created");
		assetXml->LinkEndChild(createXml);

		{
			TiXmlText* text = new TiXmlText(createDateTime());
			createXml->LinkEndChild(text);
		}

		TiXmlElement* modifiedXml = new TiXmlElement("modified");
		assetXml->LinkEndChild(modifiedXml);

		{
			TiXmlText* text = new TiXmlText(createDateTime());
			modifiedXml->LinkEndChild(text);
		}

        // <up_axis>Z_UP</up_axis>
        TiXmlElement* upAxisXml = new TiXmlElement("up_axis");
        assetXml->LinkEndChild(upAxisXml);
        TiXmlText* xmlText = new TiXmlText("Z_UP");
        upAxisXml->LinkEndChild(xmlText);
	}

    void writeInput(const MeshPtr& mesh, TiXmlElement* parentXml)
    {
        TiXmlElement* inputXml = new TiXmlElement("input");
        parentXml->LinkEndChild(inputXml);

        inputXml->SetAttribute("offset", "0");
        inputXml->SetAttribute("semantic", "VERTEX");

        std::string sourceStr = '#' + createVerticesId(mesh);
        inputXml->SetAttribute("source", sourceStr);
    }

    void writePH(const PolygonsPtr& polygons, TiXmlElement* polygonsXml)
    {
        TiXmlElement* phXml = new TiXmlElement("ph");
        polygonsXml->LinkEndChild(phXml);

        writeP(polygons->getIndices(), phXml);

        const Holes& holes = polygons->getHoles();
        for (Holes::const_iterator it = holes.begin(); it != holes.end(); ++it)
        {
            writeH(*it, phXml);
        }
    }

    void writePolygons(const Primitives& primitives, const MeshPtr& mesh, TiXmlElement* meshXml)
    {
        // TODO: Group polygons by material
        typedef boost::unordered_map<MaterialPtr, Primitives> OrderedPrimitives;
        OrderedPrimitives orderedPrimitives;

        for (Primitives::const_iterator it = primitives.begin(); it != primitives.end(); ++it)
        {
            PrimitivePtr primitive = *it;
            MaterialPtr material = primitive->getMaterial().lock();

            OrderedPrimitives::iterator it2 = orderedPrimitives.find(material);

            if (it2 == orderedPrimitives.end())
            {
                Primitives temp;
                temp.push_back(primitive);

                orderedPrimitives.emplace(material, temp);
            }
            else
            {
                it2->second.push_back(primitive);
            }
        }

        for (OrderedPrimitives::const_iterator it = orderedPrimitives.begin(); it != orderedPrimitives.end(); ++it)
        {
            const Primitives& primitives = it->second;

            TiXmlElement* polygonsXml;

            if (primitives.front()->getType() == col::TRIANGLES)
            {
                polygonsXml = new TiXmlElement("triangles");
            }
            else
            {
                polygonsXml = new TiXmlElement("polygons");
            }
            meshXml->LinkEndChild(polygonsXml);

            if (it->first.use_count() > 0)
            {
                polygonsXml->SetAttribute("material", createMaterialReference(it->first));
            }

            writeInput(mesh, polygonsXml);

            Indices moreIndices;

            for (Primitives::const_iterator it = primitives.begin(); it != primitives.end(); ++it)
            {
                PrimitivePtr primitive = *it;

                if (primitive->getType() == POLYGONS)
                {
                    PolygonsPtr polygons = boost::static_pointer_cast<Polygons>(primitive);

                    if (polygons->hasHoles())
                    {
                        writePH(polygons, polygonsXml);
                    }
                    else
                    {
                        writeP(polygons->getIndices(), polygonsXml);
                    }
                }
                else
                {
                    const Indices& indices = primitive->getIndices();
                    std::copy(indices.begin(), indices.end(), std::back_inserter(moreIndices));
                }
            }

            if (!moreIndices.empty())
            {
                writeP(moreIndices, polygonsXml);

                std::string count = boost::lexical_cast<std::string>(moreIndices.size() / 3);
                polygonsXml->SetAttribute("count", count);
            }
            else
            {
                std::string count = boost::lexical_cast<std::string>(primitives.size());
                polygonsXml->SetAttribute("count", count);
            }

        }
    }

    void writeFloatArray(const std::string& id, const std::vector<double>& floatArray, TiXmlElement* sourceXml)
	{
		TiXmlElement* floatArrayXml = new TiXmlElement("float_array");
		sourceXml->LinkEndChild(floatArrayXml);

		floatArrayXml->SetAttribute("id", id);

		std::string count = boost::lexical_cast<std::string>(floatArray.size());
		floatArrayXml->SetAttribute("count", count);

        std::string floatArrayStr = complexJoin(floatArray, " ");

		TiXmlText* floatArrayText = new TiXmlText(floatArrayStr);
		floatArrayXml->LinkEndChild(floatArrayText);
	}

    template <typename Op>
    std::vector<double> join(const Vertices& vertices, Op op)
    {
        std::vector<double> res;

        for (Vertices::const_iterator it = vertices.begin(); it != vertices.end(); ++it)
        {
            op(*it, res);
        }

        return res;
    }

    void joinPosition(const Vertex& vertex, std::vector<double>& res)
    {
        Vector3 vec = vertex.getPosition();

        res.push_back(vec.getX());
        res.push_back(vec.getY());
        res.push_back(vec.getZ());
	}

    void joinNormal(const Vertex& vertex, std::vector<double>& res)
    {
        Vector3 vec = vertex.getNormal();
        res.push_back(vec.getX());
        res.push_back(vec.getY());
        res.push_back(vec.getZ());
    }

    void joinTextureCoordinate(const Vertex& vertex, std::vector<double>& res)
    {
        if (vertex.getTextureCoordinates())
        {
            Vector2 vec = *vertex.getTextureCoordinates();
            res.push_back(vec.getX());
            res.push_back(vec.getY());
        }
        else
        {
            res.push_back(0.0);
            res.push_back(0.0);
        }
    }

	void writeDefaultPositionTechnique(const MeshPtr& mesh, TiXmlElement* sourceXml)
	{
		const size_t STRIDE = 3; // X, Y, Z
		size_t count = mesh->getVertices().size();

		TiXmlElement* techniqueCommonXml = new TiXmlElement("technique_common");
		sourceXml->LinkEndChild(techniqueCommonXml);

		TiXmlElement* accessorXml = new TiXmlElement("accessor");
		techniqueCommonXml->LinkEndChild(accessorXml);

        accessorXml->SetAttribute("count", boost::lexical_cast<std::string>(count));
		accessorXml->SetAttribute("stride", 3);
		accessorXml->SetAttribute("source", '#' + createPositionsArrayId(mesh));

		TiXmlElement* paramXml = new TiXmlElement("param");
		accessorXml->LinkEndChild(paramXml);
		paramXml->SetAttribute("name", "X");
		paramXml->SetAttribute("type", "float");
		paramXml = new TiXmlElement("param");
		accessorXml->LinkEndChild(paramXml);
		paramXml->SetAttribute("name", "Y");
		paramXml->SetAttribute("type", "float");
		paramXml = new TiXmlElement("param");
		accessorXml->LinkEndChild(paramXml);
		paramXml->SetAttribute("name", "Z");
		paramXml->SetAttribute("type", "float");
	}

    void writeDefaultUvTechnique(const MeshPtr& mesh, TiXmlElement* sourceXml)
    {
        const size_t STRIDE = 2; // S, T
        size_t count = mesh->getVertices().size();

        TiXmlElement* techniqueCommonXml = new TiXmlElement("technique_common");
        sourceXml->LinkEndChild(techniqueCommonXml);

        TiXmlElement* accessorXml = new TiXmlElement("accessor");
        techniqueCommonXml->LinkEndChild(accessorXml);

        accessorXml->SetAttribute("count", boost::lexical_cast<std::string>(count));
        accessorXml->SetAttribute("stride", STRIDE);
        accessorXml->SetAttribute("source", '#' + createTextureCoordinatesArrayId(mesh));

        TiXmlElement* paramXml = new TiXmlElement("param");
        accessorXml->LinkEndChild(paramXml);
        paramXml->SetAttribute("name", "S");
        paramXml->SetAttribute("type", "float");
        paramXml = new TiXmlElement("param");
        accessorXml->LinkEndChild(paramXml);
        paramXml->SetAttribute("name", "T");
        paramXml->SetAttribute("type", "float");
    }

    void writePositionSource(const MeshPtr& mesh, TiXmlElement* meshXml)
	{
		TiXmlElement* sourceXml = new TiXmlElement("source");
		meshXml->LinkEndChild(sourceXml);

		sourceXml->SetAttribute("id", createPositionsId(mesh));

        std::vector<double> positions = join(mesh->getVertices(), joinPosition);

		writeFloatArray(createPositionsArrayId(mesh), positions, sourceXml);
		writeDefaultPositionTechnique(mesh, sourceXml);
	}

    void writeNormalsSource(const MeshPtr& mesh, TiXmlElement* meshXml)
    {
        TiXmlElement* sourceXml = new TiXmlElement("source");
        meshXml->LinkEndChild(sourceXml);

        sourceXml->SetAttribute("id", createNormalsId(mesh));

        std::vector<double> normals = join(mesh->getVertices(), joinNormal);

        writeFloatArray(createNormalsArrayId(mesh), normals, sourceXml);
        // TODO: Wrong! PositionsTechnique uses positions array
        writeDefaultPositionTechnique(mesh, sourceXml);
    }

    void writeTextureCoordinatesSource(const MeshPtr& mesh, TiXmlElement* meshXml)
    {
        TiXmlElement* sourceXml = new TiXmlElement("source");
        meshXml->LinkEndChild(sourceXml);

        sourceXml->SetAttribute("id", createTextureCoordinatesId(mesh));

        std::vector<double> textureCoordinates = join(mesh->getVertices(), joinTextureCoordinate);

        writeFloatArray(createTextureCoordinatesArrayId(mesh), textureCoordinates, sourceXml);
        writeDefaultUvTechnique(mesh, sourceXml);
    }

	void writeVertices(const MeshPtr& mesh, TiXmlElement* meshXml)
	{
		TiXmlElement* verticesXml = new TiXmlElement("vertices");
		meshXml->LinkEndChild(verticesXml);

		verticesXml->SetAttribute("id", createVerticesId(mesh));

		// Positions
        TiXmlElement* inputXml = new TiXmlElement("input");
		verticesXml->LinkEndChild(inputXml);

        inputXml->SetAttribute("source", '#' + createPositionsId(mesh));
		inputXml->SetAttribute("semantic", "POSITION");

        // Normals
        inputXml = new TiXmlElement("input");
        verticesXml->LinkEndChild(inputXml);

        inputXml->SetAttribute("source", '#' + createNormalsId(mesh));
        inputXml->SetAttribute("semantic", "NORMAL");

        // Texture coordinates
        inputXml = new TiXmlElement("input");
        verticesXml->LinkEndChild(inputXml);

        inputXml->SetAttribute("source", '#' + createTextureCoordinatesId(mesh));
        inputXml->SetAttribute("semantic", "TEXCOORD");
	}

	void writeMesh(const MeshPtr& mesh, TiXmlElement* geometryXml)
	{
		TiXmlElement* meshXml = new TiXmlElement("mesh");
		geometryXml->LinkEndChild(meshXml);

		writePositionSource(mesh, meshXml);
        writeNormalsSource(mesh, meshXml);
        writeTextureCoordinatesSource(mesh, meshXml);
		writeVertices(mesh, meshXml);

        const Primitives& primitives = mesh->getPrimitives();

        // TODO: Enable/disable merges
        Primitives triangless;
        Primitives polygonss;

        for (Primitives::const_iterator it = primitives.begin(); it != primitives.end(); ++it)
        {
            PrimitivePtr primitive = *it;

            switch (primitive->getType())
            {
            case col::POLYGONS:
                {
                    PolygonsPtr polygons = boost::static_pointer_cast<Polygons>(primitive);
                    //writePolygons(polygons, mesh, meshXml);
                    polygonss.push_back(polygons);

                    break;
                }
            case col::TRIANGLES:
                {
                    TrianglesPtr triangles = boost::static_pointer_cast<Triangles>(primitive);
                    //writeTriangles(triangles, mesh, meshXml);
                    triangless.push_back(triangles);

                    break;
                }
            }
        }

        if (!triangless.empty())
        {
            writePolygons(triangless, mesh, meshXml);
        }

        if (!polygonss.empty())
        {
            writePolygons(polygonss, mesh, meshXml);
        }
	}

	void writeGeometry(const MeshPtr& mesh, TiXmlElement* libraryGeometriesXml)
	{
		TiXmlElement* geometryXml = new TiXmlElement("geometry");
		libraryGeometriesXml->LinkEndChild(geometryXml);

		geometryXml->SetAttribute("id", createGeometryId(mesh));

		writeMesh(mesh, geometryXml);
	}

	void writeLibraryGeometries(const MeshLibrary& meshLibrary, TiXmlElement* colladaXml)
	{
        const Meshs& meshs = meshLibrary.getMeshs();

        if (!meshs.empty())
        {
		    TiXmlElement* libraryGeometriesXml = new TiXmlElement("library_geometries");
		    colladaXml->LinkEndChild(libraryGeometriesXml);

		    for (Meshs::const_iterator it = meshs.begin(); it != meshs.end(); ++it)
		    {
			    writeGeometry(*it, libraryGeometriesXml);
		    }
        }
	}

	void writeInstanceGeometry(const MeshPtr& mesh, const MaterialPtr& material, TiXmlElement* nodeXml)
	{
		TiXmlElement* instanceGeometryXml = new TiXmlElement("instance_geometry");
		nodeXml->LinkEndChild(instanceGeometryXml);

		std::string idRef = '#' + createGeometryId(mesh);

		instanceGeometryXml->SetAttribute("url", idRef);

        if (mesh->hasMaterials())
        {
            TiXmlElement* bindMaterialXml = new TiXmlElement("bind_material");
            instanceGeometryXml->LinkEndChild(bindMaterialXml);

            TiXmlElement* techniqueCommonXml = new TiXmlElement("technique_common");
            bindMaterialXml->LinkEndChild(techniqueCommonXml);

            const Primitives& primitives = mesh->getPrimitives();

            boost::unordered_set<MaterialPtr> boundMaterials;

            for (Primitives::const_iterator it = primitives.begin(); it != primitives.end(); ++it)
            {
                const PrimitivePtr& primitive = *it;

                // A material for this primitive exists (use_count != 0)
                if (!primitive->getMaterial().expired())
                {
                    MaterialPtr material = primitive->getMaterial().lock();

                    boost::unordered_set<MaterialPtr>::const_iterator it = boundMaterials.find(material);

                    if (it == boundMaterials.end())
                    {
                        boundMaterials.insert(material);

                        std::string symbol = createMaterialReference(primitive);
                        // TODO: There is another higher scope material -> confusing

                        TiXmlElement* instanceMaterialXml = new TiXmlElement("instance_material");
                        techniqueCommonXml->LinkEndChild(instanceMaterialXml);
                        instanceMaterialXml->SetAttribute("symbol", symbol);
                        instanceMaterialXml->SetAttribute("target", '#' + material->getId());

                        if (material->getTexture())
                        {
                            TiXmlElement* bindVertexInputXml = new TiXmlElement("bind_vertex_input");
                            instanceMaterialXml->LinkEndChild(bindVertexInputXml);
                            bindVertexInputXml->SetAttribute("semantic", "TEX0");
                            bindVertexInputXml->SetAttribute("input_semantic", "TEXCOORD");
                            bindVertexInputXml->SetAttribute("input_set", "0");
                        }
                    }
                }
            }

        }
	}

    void writeTitleAsset(const std::string& title, TiXmlElement* parentXml)
    {
        TiXmlElement* assetXml = new TiXmlElement("asset");
        parentXml->LinkEndChild(assetXml);

        TiXmlElement* titleXml = new TiXmlElement("title");
        assetXml->LinkEndChild(titleXml);

        TiXmlText* textXml = new TiXmlText(title);
        titleXml->LinkEndChild(textXml);
    }

    void writeNodeInstanceXml(const NodePtr& node, TiXmlElement* parentXml)
    {
        TiXmlElement* instanceNodeXml = new TiXmlElement("instance_node");
        parentXml->LinkEndChild(instanceNodeXml);

        instanceNodeXml->SetAttribute("url", '#' + node->getId());
    }

    void writeNodeXml(const NodePtr& node, TiXmlElement* parentXml)
    {
        TiXmlElement* nodeXml = new TiXmlElement("node");
        parentXml->LinkEndChild(nodeXml);

        nodeXml->SetAttribute("id", node->getId());

        nodeXml->SetAttribute("name", makeValidNCName(node->getName()));
        //writeTitleAsset(node->getName(), nodeXml);

        if (node->getTransformation())
        {
            TiXmlElement* matrixXml = new TiXmlElement("matrix");
            nodeXml->LinkEndChild(matrixXml);

            std::stringstream text;

            col::Matrix4 transformation = *node->getTransformation();
            text << transformation;

            TiXmlText* matrixText = new TiXmlText(text.str());
            matrixXml->LinkEndChild(matrixText);
        }

        if (node->getMesh().lock().get() != NULL)
        {
            writeInstanceGeometry(node->getMesh().lock(), node->getMaterial().lock(), nodeXml);
        }

        const Children& children = node->getChildren();
        for (Children::const_iterator it = children.begin(); it != children.end(); ++it)
        {
            NodePtr node = it->get<0>();

            if (it->get<1>() == REFERENCE)
            {
                writeNodeInstanceXml(node, nodeXml);
            }
            else if (it->get<1>() == INSTANCE)
            {
                writeNodeXml(node, nodeXml);
            }
        }
    }

    void writeLibraryNodes(const Scene& scene, TiXmlElement* colladaXml)
    {

    }

	void writeLibraryVisualScenes(const Scene& scene, const NodeLibrary& nodesLibrary, TiXmlElement* colladaXml)
	{
        if (!scene.isEmpty())
        {
            // TODO:
            if (true)
            {
                // Visual scene part
                TiXmlElement* libraryVisualScenesXml = new TiXmlElement("library_visual_scenes");
                colladaXml->LinkEndChild(libraryVisualScenesXml);

                TiXmlElement* visualSceneXml = new TiXmlElement("visual_scene");
                libraryVisualScenesXml->LinkEndChild(visualSceneXml);

                visualSceneXml->SetAttribute("id", "default-scene");

                {
                    const Nodes& children = scene.getChildren();
                    for (Nodes::const_iterator it = children.begin(); it != children.end(); ++it)
                    {
                        writeNodeXml(*it, visualSceneXml);
                    }
                }

                // Library nodes part

                {
                    const Nodes& children = nodesLibrary.getItems();

                    if (!children.empty())
                    {
                        TiXmlElement* libraryNodesXml = new TiXmlElement("library_nodes");
                        colladaXml->LinkEndChild(libraryNodesXml);

                        for (Nodes::const_iterator it = children.begin(); it != children.end(); ++it)
                        {
                            NodePtr node = *it;

                            // Nodes library output
                            writeNodeXml(*it, libraryNodesXml);
                        }
                    }
                }
            }
            else
            {
                TiXmlElement* libraryVisualScenesXml = new TiXmlElement("library_visual_scenes");
                colladaXml->LinkEndChild(libraryVisualScenesXml);

                // 		<visual_scene id="scene">
                // 			<node id="object">
                // 			<instance_geometry url="#test" />
                // 			</node>
                // 		</visual_scene>

                TiXmlElement* visualSceneXml = new TiXmlElement("visual_scene");
                libraryVisualScenesXml->LinkEndChild(visualSceneXml);

                visualSceneXml->SetAttribute("id", "default-scene");

                const Nodes& children = scene.getChildren();

                for (Nodes::const_iterator it = children.begin(); it != children.end(); ++it)
                {
                    writeNodeXml(*it, visualSceneXml);
                }
            }
        }
	}

	void writeScene(TiXmlElement* colladaXml)
	{
		TiXmlElement* sceneXml = new TiXmlElement("scene");
		colladaXml->LinkEndChild(sceneXml);

		// <instance_visual_scene url="#scene" />

		TiXmlElement* instanceVisualSceneXml = new TiXmlElement("instance_visual_scene");
		sceneXml->LinkEndChild(instanceVisualSceneXml);

		instanceVisualSceneXml->SetAttribute("url", "#default-scene");
	}

    void writeMaterial(const MaterialPtr& material, TiXmlElement* libraryMaterialsXml)
    {
        TiXmlElement* materialXml = new TiXmlElement("material");
        libraryMaterialsXml->LinkEndChild(materialXml);
        materialXml->SetAttribute("id", material->getId());

        TiXmlElement* instanceEffectXml = new TiXmlElement("instance_effect");
        materialXml->LinkEndChild(instanceEffectXml);
        instanceEffectXml->SetAttribute("url", "#effect-" + material->getId());
    }

    void writeLibraryMaterials(const MaterialLibrary& materialLib, TiXmlElement* colladaXml)
    {
        const Materials& materials = materialLib.getMaterials();

        if (materials.size() > 0)
        {
            TiXmlElement* libraryMaterialsXml = new TiXmlElement("library_materials");
            colladaXml->LinkEndChild(libraryMaterialsXml);

            for (Materials::const_iterator it = materials.begin(); it != materials.end(); ++it)
            {
                writeMaterial(*it, libraryMaterialsXml);
            }
        }
    }

    void writeSurfaceParam(const TexturePtr& texture, TiXmlElement* profileCommonXml)
    {
        TiXmlElement* newParamXml = new TiXmlElement("newparam");
        profileCommonXml->LinkEndChild(newParamXml);
        newParamXml->SetAttribute("sid", createTextureSurfaceId(texture));

        // TODO:
        TiXmlElement* surfaceXml = new TiXmlElement("surface");
        newParamXml->LinkEndChild(surfaceXml);
        surfaceXml->SetAttribute("type", "2D");

        TiXmlElement* initFromXml = new TiXmlElement("init_from");
        surfaceXml->LinkEndChild(initFromXml);

        // TODO:
        TiXmlText* xmlText = new TiXmlText(texture->getImage()->getId());
        initFromXml->LinkEndChild(xmlText);
    }

    void writeSamplerParam(const TexturePtr& texture, TiXmlElement* profileCommonXml)
    {
        TiXmlElement* newParamXml = new TiXmlElement("newparam");
        profileCommonXml->LinkEndChild(newParamXml);
        newParamXml->SetAttribute("sid", createTextureSamplerId(texture));

        // TODO:
        TiXmlElement* sampler2DXml = new TiXmlElement("sampler2D");
        newParamXml->LinkEndChild(sampler2DXml);

        TiXmlElement* sourceXml = new TiXmlElement("source");
        sampler2DXml->LinkEndChild(sourceXml);

        TiXmlText* xmlText = new TiXmlText(createTextureSurfaceId(texture));
        sourceXml->LinkEndChild(xmlText);

        // WRAP is default
        if (texture->getWrap() != col::WRAP)
        {
            std::string wrapText = boost::lexical_cast<std::string>(texture->getWrap());

            TiXmlElement* wrapSXml = new TiXmlElement("wrap_s");
            sampler2DXml->LinkEndChild(wrapSXml);

            xmlText = new TiXmlText(wrapText);
            wrapSXml->LinkEndChild(xmlText);

            TiXmlElement* wrapTXml = new TiXmlElement("wrap_t");
            sampler2DXml->LinkEndChild(wrapTXml);

            xmlText = new TiXmlText(wrapText);
            wrapTXml->LinkEndChild(xmlText);
        }
    }

    void writeEffect(const MaterialPtr& material, TiXmlElement* effectsLibraryXml)
    {
        //      <effect id="red-effect">
        // 			<profile_COMMON>
        // 				<technique sid="COMMON">
        // 					<phong>
        // 						<diffuse>
        // 							<color>1 0 0 1</color>
        // 						</diffuse>
        // 					</phong>
        // 				</technique>
        // 			</profile_COMMON>
        // 		</effect>

        TiXmlElement* effectXml = new TiXmlElement("effect");
        effectsLibraryXml->LinkEndChild(effectXml);
        effectXml->SetAttribute("id", "effect-" + material->getId());

        TiXmlElement* profileCommonXml = new TiXmlElement("profile_COMMON");
        effectXml->LinkEndChild(profileCommonXml);

        // begin params
        if (material->getTexture())
        {
            writeSurfaceParam(*material->getTexture(), profileCommonXml);
            writeSamplerParam(*material->getTexture(), profileCommonXml);
        }
        // end params

        TiXmlElement* techniqueXml = new TiXmlElement("technique");
        profileCommonXml->LinkEndChild(techniqueXml);
        techniqueXml->SetAttribute("sid", "COMMON");

        TiXmlElement* phongXml = new TiXmlElement("lambert");
        techniqueXml->LinkEndChild(phongXml);

        TiXmlElement* diffuseXml = new TiXmlElement("diffuse");
        phongXml->LinkEndChild(diffuseXml);

        if (material->getTexture())
        {
            TiXmlElement* textureXml = new TiXmlElement("texture");
            diffuseXml->LinkEndChild(textureXml);

            std::string samplerId = createTextureSamplerId(*material->getTexture());

            textureXml->SetAttribute("texture", samplerId);
            textureXml->SetAttribute("texcoord", "TEX0");
        }
        else if (material->getColor())
        {
            Color color = *material->getColor();

            TiXmlElement* colorXml = new TiXmlElement("color");
            diffuseXml->LinkEndChild(colorXml);

            std::string colorText = boost::lexical_cast<std::string>(color);

            TiXmlText* colorTextXml = new TiXmlText(colorText);
            colorXml->LinkEndChild(colorTextXml);
        }
        else
        {
            // TODO: FAIL!!!
            // Empty materials result in invalid dom tree.
            // A material needs one of color or texture.
            //assert(false);
            throw std::runtime_error("A material needs either a texture or a color");
        }

    }

    void writeLibraryEffects(const MaterialLibrary& materialLib, TiXmlElement* colladaXml)
    {
        const Materials& materials = materialLib.getMaterials();

        if (!materials.empty())
        {
            TiXmlElement* libraryEffectsXml = new TiXmlElement("library_effects");
            colladaXml->LinkEndChild(libraryEffectsXml);

            for (Materials::const_iterator it = materials.begin(); it != materials.end(); ++it)
            {
                writeEffect(*it, libraryEffectsXml);
            }
        }
    }

    void writeImage(const ImagePtr& image, TiXmlElement* libraryImagesXml)
    {
        TiXmlElement* imageXml = new TiXmlElement("image");
        libraryImagesXml->LinkEndChild(imageXml);

        imageXml->SetAttribute("id", image->getId());

        TiXmlElement* initFromXml = new TiXmlElement("init_from");
        imageXml->LinkEndChild(initFromXml);

        TiXmlText* xmlText = new TiXmlText(image->getPath().string());
        initFromXml->LinkEndChild(xmlText);
    }

    void writeLibraryImages(const ImageLibrary& imageLib, TiXmlElement* colladaXml)
    {
        const ImageLibrary::Items images = imageLib.getItems();

        if (!images.empty())
        {
            TiXmlElement* libraryImagesXml = new TiXmlElement("library_images");
            colladaXml->LinkEndChild(libraryImagesXml);

            for (ImageLibrary::Items::const_iterator it = images.begin(); it != images.end(); ++it)
            {
                writeImage(*it, libraryImagesXml);
            }
        }
    }

	Writer::Writer(const Context& context)
		: m_context(context)
        , m_scene(m_context.getScene())
        , m_meshLib(m_context.getMeshLibrary())
        , m_materialLib(m_context.getMaterialLibrary())
        , m_imageLib(m_context.getImageLibrary())
        , m_nodeLib(m_context.getNodeLibrary())
        , m_schemaLocationEnabled(false)
	{

	}

	void Writer::write(std::ostream& out)
	{
		TiXmlDocument doc;
		TiXmlDeclaration* decl = new TiXmlDeclaration("1.0", "UTF-8", "");
		doc.LinkEndChild(decl);

		TiXmlElement* colladaXml = new TiXmlElement("COLLADA");
		doc.LinkEndChild(colladaXml);

		colladaXml->SetAttribute("xmlns", XMLNS);
		colladaXml->SetAttribute("version", VERSION);

        if (m_schemaLocationEnabled)
        {
            colladaXml->SetAttribute("schemaLocation", XMLNS + " " + SCHEMA_LOCATION);
        }

		writeAsset(colladaXml);
        writeLibraryImages(m_imageLib, colladaXml);
        writeLibraryEffects(m_materialLib, colladaXml);
        writeLibraryMaterials(m_materialLib, colladaXml);
		writeLibraryGeometries(m_meshLib, colladaXml);
		writeLibraryVisualScenes(m_scene, m_nodeLib, colladaXml);
		writeScene(colladaXml);

		out << doc;
	}

    void write(Writer& writer, const std::string& path)
    {
        boost::iostreams::stream<boost::iostreams::file_sink> out(path);
        writer.write(out);
    }

    void write(Writer& writer, const std::wstring& path)
    {
        boost::filesystem::wpath p(path);
        boost::iostreams::stream<boost::iostreams::file_descriptor_sink> out(p);
        writer.write(out);
    }

}

ext: cpp

max_stars_repo_name: jbxplan/GMLToolbox-src

max_issues_repo_name: jbxplan/GMLToolbox-src

max_forks_repo_name: jbxplan/GMLToolbox-src


text:
#ifndef __CONFIG_KEEPER_HPP__
#define __CONFIG_KEEPER_HPP__

/*** Included Header Files ***/
#include <boost/program_options.hpp>
#include <boost/lexical_cast.hpp>
#include <vector>
#include <set>
#include <ctype.h>
#include <tchar.h>

/***************************************************************************************/

class ConfigKeeper {
private:
	boost::program_options::options_description _desc;
	boost::program_options::options_description _hidden;
	boost::program_options::options_description _env;
	boost::program_options::options_description _commandLine;
	boost::program_options::positional_options_description _posDesc;

	boost::program_options::variables_map _variablesMap;
	ConfigKeeper( void );

	typedef std::set< std::string> EnviromentVarNameSet;

	class EnvironmentVarNameSetInit {
	private:
		EnviromentVarNameSet _environmentVarNameSet;

	public:
		EnvironmentVarNameSetInit( void ) {
			_environmentVarNameSet.insert( "DESERT_PATH" );
		}

		EnviromentVarNameSet &getEnvironmentVarNameSet( void ) {
			return _environmentVarNameSet;
		}
	};

	static EnviromentVarNameSet &getEnvironmentVarNameSet( void ) {
		static EnvironmentVarNameSetInit environmentVarNameSetInit;
		return environmentVarNameSetInit.getEnvironmentVarNameSet();
	}

	static std::string mapEnv( std::string str ) {
		if (  getEnvironmentVarNameSet().find( str ) == getEnvironmentVarNameSet().end() ) {
			return "";
		}

		std::transform( str.begin(), str.end(), str.begin(), tolower );
		return str;
	}

public:
	static ConfigKeeper &getSingleton( void ) {
		static ConfigKeeper configKeeper;
		return configKeeper;
	}

	bool processCommandLineArguments( int argc, TCHAR *argv[] );

	std::string getStringValue( const std::string &name ) { return _variablesMap[ name ].as< std::string >(); }
	std::vector< std::string > getStringVector( const std::string &name ) {
		return _variablesMap[ name ].as<  std::vector< std::string >  >();
	}
	int getCount( const std::string &name ) { return _variablesMap.count( name ); }
	boost::program_options::options_description getDescription( void ) { return _desc; }
};

/***************************************************************************************/

#endif //__CONFIG_KEEPER_HPP__

ext: hpp

max_stars_repo_name: lefevre-fraser/openmeta-mms

max_issues_repo_name: lefevre-fraser/openmeta-mms

max_forks_repo_name: lefevre-fraser/openmeta-mms


text:
/**
 * Copyright 2022 Scott Brauer
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an  BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @file   main.cpp
 * @author Scott Brauer
 * @date   01-28-2022
 */

#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <cstdlib>
#include <sys/wait.h>
#include <sys/types.h>
#include <string.h>
using namespace std;

#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream_buffer.hpp>
#include <boost/iostreams/stream.hpp>

#include "easylogging++.h"

INITIALIZE_EASYLOGGINGPP

int main(int argc, char **argv)
{
	int af[2];
    pipe(af);

	pid_t pid1;
    pid1 = fork();

    int nbytes, wbytes;
    char inside[20];

    if(pid1 == -1)
    {
        cout << "No child process formed: " << getpid() <<endl;
        exit(1);
    }
    else if(pid1 == 0)
    {
    	// Child
    	cout << pid1 << ": inchild" << endl;
    	dup2(af[1],1);
        close(af[0]);
        //wbytes = write(af[1], "Hello World", 12);
        cout << "\t" << pid1 << ": Hello World" << endl;
        cout << "\t" << pid1 << ": wrote bytes: " << wbytes<<endl;
        cout << "\t" << pid1 << ": Child(write) inside string: " << af[1] << endl;
        close(af[1]);
        cout << "\t" << pid1 << ": in child's end" << endl;
        exit(0);
    }
    else
    {
    	// Parent
    	cout << pid1 << ": inparent" <<endl;
        close(af[1]);

        boost::iostreams::file_descriptor_source src{af[0], boost::iostreams::close_handle};
        boost::iostreams::stream<boost::iostreams::file_descriptor_source> is{src};

        std::string s;
        std::getline(is, s);
        std::cout << pid1 << ": " << s << endl;
        std::getline(is, s);
        std::cout << pid1 << ": " << s << endl;
        std::getline(is, s);
        std::cout << pid1 << ": " << s << endl;
        std::getline(is, s);
        std::cout << pid1 << ": " << s << endl;
        std::getline(is, s);
        std::cout << pid1 << ": " << s << endl;

 //       nbytes = read(af[0], inside, 12);
 //       cout << pid1 << ": read bytes: "<< nbytes << endl;
 //       cout << pid1 << ": parent(read) inside descriptor: " << inside << endl;

//        nbytes = read(af[0], inside, 12);
//        cout << pid1 << ": read bytes: "<< nbytes << endl;
//        cout << pid1 << ": parent(read) inside descriptor: " << inside << endl;

//        close(af[0]);
        cout << pid1 << ": in parents's end" << endl;
        exit(0);
    }

    /*
    if(pid1 == -1)
    {
        cout << "No child process formed: " << getpid() <<endl;
        exit(1);
    }
    else if(pid1 == 0)
    {
    	cout << pid1 << ": inchild" <<endl;
        close(af[1]);
        nbytes = read(af[0],inside,strlen(inside));
        cout << pid1 << ": read bytes: "<< nbytes << endl;
        cout << pid1 << ": child(read) inside descriptor: " << inside << endl;
        close(af[0]);
        cout << pid1 << ": in child's end" << endl;
        exit(0);
    }
    else
    {
    	cout << pid1 << ": inparent" << endl;
        close(af[0]);
        wbytes = write(af[1],"Hello World",12);
        cout << pid1 << ": wrote bytes: " << wbytes<<endl;
        cout << pid1 << ": Parent(write) inside string: " << af[1] << endl;
        close(af[1]);
        cout << pid1 << ": in parent's end" << endl;
        exit(0);
    }
    */

    return 0;
}


text:
//---------------------------------------------------------------------------//
// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com>
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
// See http://boostorg.github.com/compute for more information.
//---------------------------------------------------------------------------//

#define BOOST_TEST_MODULE TestKernel
#include <boost/test/unit_test.hpp>

#include <boost/compute/buffer.hpp>
#include <boost/compute/kernel.hpp>
#include <boost/compute/system.hpp>
#include <boost/compute/utility/source.hpp>

#include "context_setup.hpp"
#include "check_macros.hpp"

namespace compute = boost::compute;

BOOST_AUTO_TEST_CASE(name)
{
    compute::kernel foo = compute::kernel::create_with_source(
        "__kernel void foo(int x) { }", "foo", context
    );
    BOOST_CHECK_EQUAL(foo.name(), "foo");

    compute::kernel bar = compute::kernel::create_with_source(
        "__kernel void bar(float x) { }", "bar", context
    );
    BOOST_CHECK_EQUAL(bar.name(), "bar");
}

BOOST_AUTO_TEST_CASE(arity)
{
    compute::kernel foo = compute::kernel::create_with_source(
        "__kernel void foo(int x) { }", "foo", context
    );
    BOOST_CHECK_EQUAL(foo.arity(), size_t(1));

    compute::kernel bar = compute::kernel::create_with_source(
        "__kernel void bar(float x, float y) { }", "bar", context
    );
    BOOST_CHECK_EQUAL(bar.arity(), size_t(2));

    compute::kernel baz = compute::kernel::create_with_source(
        "__kernel void baz(char x, char y, char z) { }", "baz", context
    );
    BOOST_CHECK_EQUAL(baz.arity(), size_t(3));
}

BOOST_AUTO_TEST_CASE(set_buffer_arg)
{
    const char source[] = BOOST_COMPUTE_STRINGIZE_SOURCE(
        __kernel void foo(__global int *x, __global int *y)
        {
            x[get_global_id(0)] = -y[get_global_id(0)];
        }
    );

    compute::kernel foo =
        compute::kernel::create_with_source(source, "foo", context);

    compute::buffer x(context, 16);
    compute::buffer y(context, 16);

    foo.set_arg(0, x);
    foo.set_arg(1, y.get());
}

BOOST_AUTO_TEST_CASE(get_work_group_info)
{
    const char source[] =
    "__kernel void sum(__global const float *input,\n"
    "                  __global float *output)\n"
    "{\n"
    "    __local float scratch[16];\n"
    "    const uint gid = get_global_id(0);\n"
    "    const uint lid = get_local_id(0);\n"
    "    if(lid < 16)\n"
    "        scratch[lid] = input[gid];\n"
    "}\n";

    compute::program program =
        compute::program::create_with_source(source, context);

    program.build();

    compute::kernel kernel = program.create_kernel("sum");

    using compute::ulong_;

    // get local memory size
    kernel.get_work_group_info<ulong_>(device, CL_KERNEL_LOCAL_MEM_SIZE);

    // check work group size
    size_t work_group_size =
        kernel.get_work_group_info<size_t>(device, CL_KERNEL_WORK_GROUP_SIZE);
    BOOST_CHECK(work_group_size >= 1);
}

#ifndef BOOST_COMPUTE_NO_VARIADIC_TEMPLATES
BOOST_AUTO_TEST_CASE(kernel_set_args)
{
    compute::kernel k = compute::kernel::create_with_source(
        "__kernel void test(int x, float y, char z) { }", "test", context
    );

    k.set_args(4, 2.4f, 'a');
}
#endif // BOOST_COMPUTE_NO_VARIADIC_TEMPLATES

#ifdef BOOST_COMPUTE_CL_VERSION_1_2
BOOST_AUTO_TEST_CASE(get_arg_info)
{
    REQUIRES_OPENCL_VERSION(1, 2);

    const char source[] = BOOST_COMPUTE_STRINGIZE_SOURCE(
        __kernel void sum_kernel(__global const int *input,
                                 const uint size,
                                 __global int *result)
        {
            int sum = 0;
            for(uint i = 0; i < size; i++){
                sum += input[i];
            }
            *result = sum;
        }
    );

    compute::program program =
        compute::program::create_with_source(source, context);

    program.build("-cl-kernel-arg-info");

    compute::kernel kernel = program.create_kernel("sum_kernel");

    BOOST_CHECK_EQUAL(kernel.get_info<CL_KERNEL_NUM_ARGS>(), compute::uint_(3));

    BOOST_CHECK_EQUAL(kernel.get_arg_info<std::string>(0, CL_KERNEL_ARG_TYPE_NAME), "int*");
    BOOST_CHECK_EQUAL(kernel.get_arg_info<std::string>(0, CL_KERNEL_ARG_NAME), "input");
    BOOST_CHECK_EQUAL(kernel.get_arg_info<std::string>(1, CL_KERNEL_ARG_TYPE_NAME), "uint");
    BOOST_CHECK_EQUAL(kernel.get_arg_info<std::string>(1, CL_KERNEL_ARG_NAME), "size");
    BOOST_CHECK_EQUAL(kernel.get_arg_info<std::string>(2, CL_KERNEL_ARG_TYPE_NAME), "int*");
    BOOST_CHECK_EQUAL(kernel.get_arg_info<std::string>(2, CL_KERNEL_ARG_NAME), "result");

    BOOST_CHECK_EQUAL(kernel.get_arg_info<CL_KERNEL_ARG_TYPE_NAME>(0), "int*");
    BOOST_CHECK_EQUAL(kernel.get_arg_info<CL_KERNEL_ARG_NAME>(0), "input");
    BOOST_CHECK_EQUAL(kernel.get_arg_info<CL_KERNEL_ARG_TYPE_NAME>(1), "uint");
    BOOST_CHECK_EQUAL(kernel.get_arg_info<CL_KERNEL_ARG_NAME>(1), "size");
    BOOST_CHECK_EQUAL(kernel.get_arg_info<CL_KERNEL_ARG_TYPE_NAME>(2), "int*");
    BOOST_CHECK_EQUAL(kernel.get_arg_info<CL_KERNEL_ARG_NAME>(2), "result");
}
#endif // BOOST_COMPUTE_CL_VERSION_1_2

#ifdef BOOST_COMPUTE_CL_VERSION_2_0
#ifndef CL_KERNEL_MAX_SUB_GROUP_SIZE_FOR_NDRANGE_KHR
    #define CL_KERNEL_MAX_SUB_GROUP_SIZE_FOR_NDRANGE_KHR CL_KERNEL_MAX_SUB_GROUP_SIZE_FOR_NDRANGE
#endif
#ifndef CL_KERNEL_SUB_GROUP_COUNT_FOR_NDRANGE_KHR
    #define CL_KERNEL_SUB_GROUP_COUNT_FOR_NDRANGE_KHR CL_KERNEL_SUB_GROUP_COUNT_FOR_NDRANGE
#endif
BOOST_AUTO_TEST_CASE(get_sub_group_info_ext)
{
    compute::kernel k = compute::kernel::create_with_source(
        "__kernel void test(float x) { }", "test", context
    );

    // get_sub_group_info(const device&, cl_kernel_sub_group_info, const std::vector<size_t>)
    std::vector<size_t> local_work_size(2, size_t(64));
    boost::optional<size_t> count = k.get_sub_group_info<size_t>(
        device,
        CL_KERNEL_SUB_GROUP_COUNT_FOR_NDRANGE_KHR,
        local_work_size
    );

    if(device.check_version(2, 1))
    {
        BOOST_CHECK(count);
    }
    else if(device.check_version(2, 0) && device.supports_extension("cl_khr_subgroups"))
    {
        // for device with cl_khr_subgroups it should return some value
        BOOST_CHECK(count);
    }
    else
    {
        // for device without cl_khr_subgroups ext it should return null optional
        BOOST_CHECK(count == boost::none);
    }

    // get_sub_group_info(const device&, cl_kernel_sub_group_info, const size_t, const void *)
    count = k.get_sub_group_info<size_t>(
        device,
        CL_KERNEL_SUB_GROUP_COUNT_FOR_NDRANGE_KHR,
        2 * sizeof(size_t),
        &local_work_size[0]
    );

    if(device.check_version(2, 1))
    {
        BOOST_CHECK(count);
    }
    else if(device.check_version(2, 0) && device.supports_extension("cl_khr_subgroups"))
    {
        // for device with cl_khr_subgroups it should return some value
        BOOST_CHECK(count);
    }
    else
    {
        // for device without cl_khr_subgroups ext it should return null optional
        BOOST_CHECK(count == boost::none);
    }
}
#endif // BOOST_COMPUTE_CL_VERSION_2_0

#ifdef BOOST_COMPUTE_CL_VERSION_2_1
BOOST_AUTO_TEST_CASE(get_sub_group_info_core)
{
    compute::kernel k = compute::kernel::create_with_source(
        "__kernel void test(float x) { }", "test", context
    );

    // get_sub_group_info(const device&, cl_kernel_sub_group_info, const size_t)
    boost::optional<std::vector<size_t>> local_size =
        k.get_sub_group_info<std::vector<size_t> >(
            device,
            CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT,
            size_t(1)
        );

    if(device.check_version(2, 1))
    {
        // for 2.1 devices it should return some value
        BOOST_CHECK(local_size);
        BOOST_CHECK(local_size.value().size() == 3);
    }
    else
    {
        // for 1.x and 2.0 devices it should return null optional,
        // because CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT is not
        // supported by cl_khr_subgroups (2.0 ext)
        BOOST_CHECK(local_size == boost::none);
    }

    // get_sub_group_info(const device&, cl_kernel_sub_group_info, const size_t)
    boost::optional<size_t> local_size_simple =
        k.get_sub_group_info<size_t>(
            device,
            CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT,
            size_t(1)
        );

    if(device.check_version(2, 1))
    {
        // for 2.1 devices it should return some value
        BOOST_CHECK(local_size_simple);
    }
    else
    {
        // for 1.x and 2.0 devices it should return null optional,
        // because CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT is not
        // supported by cl_khr_subgroups (2.0 ext)
        BOOST_CHECK(local_size_simple == boost::none);
    }

    // get_sub_group_info(const device&, cl_kernel_sub_group_info)
    boost::optional<size_t> max =
        k.get_sub_group_info<size_t>(
            device,
            CL_KERNEL_MAX_NUM_SUB_GROUPS
        );

    if(device.check_version(2, 1))
    {
        // for 2.1 devices it should return some value
        BOOST_CHECK(max);
    }
    else
    {
        // for 1.x and 2.0 devices it should return null optional,
        // because CL_KERNEL_MAX_NUM_SUB_GROUPS is not
        // supported by cl_khr_subgroups (2.0 ext)
        BOOST_CHECK(max == boost::none);
    }
}
#endif // BOOST_COMPUTE_CL_VERSION_2_1

#ifdef BOOST_COMPUTE_CL_VERSION_2_1
BOOST_AUTO_TEST_CASE(clone_kernel)
{
    REQUIRES_OPENCL_PLATFORM_VERSION(2, 1);

    compute::kernel k1 = compute::kernel::create_with_source(
        "__kernel void test(__global int * x) { x[get_global_id(0)] = get_global_id(0); }",
        "test", context
    );

    compute::buffer x(context, 5 * sizeof(compute::int_));
    k1.set_arg(0, x);

    // Clone k1 kernel
    compute::kernel k2 = k1.clone();
    // After clone k2 0th argument (__global float * x) should be set,
    // so we should be able to enqueue k2 kernel without problems
    queue.enqueue_1d_range_kernel(k2, 0, x.size() / sizeof(compute::int_), 0).wait();
}
#endif // BOOST_COMPUTE_CL_VERSION_2_1

BOOST_AUTO_TEST_SUITE_END()

max_stars_repo_name: sznaider/compute

max_issues_repo_name: sznaider/compute

max_forks_repo_name: sznaider/compute


text:
/*
 * Copyright (c) 2016 Nicholas Corgan (n.corgan@gmail.com)
 *
 * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
 * or copy at http://opensource.org/licenses/MIT)
 */

#include "utils/misc.hpp"
#include "pokemon_ndsimpl.hpp"
#include "database/id_to_index.hpp"
#include "database/id_to_string.hpp"
#include "database/index_to_string.hpp"

#include <pkmn/calculations/shininess.hpp>

#include "pksav/party_data.hpp"
#include "pksav/pksav_call.hpp"

#include <pksav/common/gen3_ribbons.h>
#include <pksav/common/markings.h>
#include <pksav/common/stats.h>
#include <pksav/gen4/text.h>
#include <pksav/gen5/text.h>
#include <pksav/math/endian.h>

#include <boost/algorithm/string.hpp>
#include <boost/assign.hpp>
#include <boost/format.hpp>

#include <cstring>
#include <ctime>
#include <random>
#include <stdexcept>

#define NDS_PC_RCAST    reinterpret_cast<pksav_nds_pc_pokemon_t*>(_native_pc)
#define NDS_PARTY_RCAST reinterpret_cast<pksav_nds_pokemon_party_data_t*>(_native_party)

namespace pkmn {

    BOOST_STATIC_CONSTEXPR int DIAMOND = 12;
    BOOST_STATIC_CONSTEXPR int PLATINUM = 14;
    BOOST_STATIC_CONSTEXPR int HEARTGOLD = 15;
    BOOST_STATIC_CONSTEXPR int SOULSILVER = 16;

    pokemon_ndsimpl::pokemon_ndsimpl(
        pkmn::database::pokemon_entry&& database_entry,
        int level
    ): pokemon_impl(std::move(database_entry)),
       _gen4(database_entry.get_game_id() >= DIAMOND and database_entry.get_game_id() <= SOULSILVER),
       _plat(database_entry.get_game_id() == PLATINUM),
       _hgss(database_entry.get_game_id() == HEARTGOLD or database_entry.get_game_id() == SOULSILVER)
    {
        _native_pc = reinterpret_cast<void*>(new pksav_nds_pc_pokemon_t);
        std::memset(_native_pc, 0, sizeof(pksav_nds_pc_pokemon_t));
        _our_pc_mem = true;

        _native_party = reinterpret_cast<void*>(new pksav_nds_pokemon_party_data_t);
        std::memset(_native_party, 0, sizeof(pksav_nds_pokemon_party_data_t));
        _our_party_mem = true;

        // Set _block pointers
        _blockA = &NDS_PC_RCAST->blocks.blockA;
        _blockB = &NDS_PC_RCAST->blocks.blockB;
        _blockC = &NDS_PC_RCAST->blocks.blockC;
        _blockD = &NDS_PC_RCAST->blocks.blockD;

        // Populate abstractions
        _update_held_item();
        _update_ribbons_map();
        _update_EV_map();
        _init_modern_IV_map(&_blockB->iv_isegg_isnicknamed);
        _init_contest_stat_map(&_blockA->contest_stats);
        _init_markings_map(&_blockA->markings);
        set_level(level);
        _update_moves(-1);
    }

    pokemon_ndsimpl::pokemon_ndsimpl(
        pksav_nds_pc_pokemon_t* pc,
        int game_id
    ): pokemon_impl(
           pksav_littleendian16(pc->blocks.blockA.species),
           game_id
       ),
       _gen4(game_id >= DIAMOND and game_id <= SOULSILVER),
       _plat(game_id == PLATINUM),
       _hgss(game_id == HEARTGOLD or game_id == SOULSILVER)
    {
        _native_pc = reinterpret_cast<void*>(pc);
        _our_pc_mem = false;

        _native_party = reinterpret_cast<void*>(new pksav_nds_pokemon_party_data_t);
        pksav::nds_pc_pokemon_to_party_data(
            _database_entry,
            reinterpret_cast<const pksav_nds_pc_pokemon_t*>(_native_pc),
            reinterpret_cast<pksav_nds_pokemon_party_data_t*>(_native_party)
        );
        _our_party_mem = true;

        // Set _block pointers
        _blockA = &NDS_PC_RCAST->blocks.blockA;
        _blockB = &NDS_PC_RCAST->blocks.blockB;
        _blockC = &NDS_PC_RCAST->blocks.blockC;
        _blockD = &NDS_PC_RCAST->blocks.blockD;

        // Populate abstractions
        _update_held_item();
        _update_ribbons_map();
        _update_EV_map();
        _init_modern_IV_map(&_blockB->iv_isegg_isnicknamed);
        _init_contest_stat_map(&_blockA->contest_stats);
        _init_markings_map(&_blockA->markings);
        _update_stat_map();
        _update_moves(-1);
    }

    pokemon_ndsimpl::pokemon_ndsimpl(
        pksav_nds_party_pokemon_t* party,
        int game_id
    ): pokemon_impl(
           pksav_littleendian16(party->pc_data.blocks.blockA.species),
           game_id
       ),
       _gen4(game_id >= DIAMOND and game_id <= SOULSILVER),
       _plat(game_id == PLATINUM),
       _hgss(game_id == HEARTGOLD or game_id == SOULSILVER)
    {
        _native_pc = reinterpret_cast<void*>(&party->pc_data;
        _our_pc_mem = false;

        _native_party = reinterpret_cast<void*>(&party->party_data);
        _our_party_mem = false;

        // Set _block pointers
        _blockA = &NDS_PC_RCAST->blocks.blockA;
        _blockB = &NDS_PC_RCAST->blocks.blockB;
        _blockC = &NDS_PC_RCAST->blocks.blockC;
        _blockD = &NDS_PC_RCAST->blocks.blockD;

        // Populate abstractions
        _update_held_item();
        _update_ribbons_map();
        _update_EV_map();
        _init_modern_IV_map(&_blockB->iv_isegg_isnicknamed);
        _init_contest_stat_map(&_blockA->contest_stats);
        _init_markings_map(&_blockA->markings);
        _update_stat_map();
        _update_moves(-1);
    }

    pokemon_ndsimpl::pokemon_ndsimpl(
        const pksav_nds_pc_pokemon_t &pc,
        int game_id
    ): pokemon_impl(
           pksav_littleendian16(pc.blocks.blockA.species),
           game_id
       ),
       _gen4(game_id >= DIAMOND and game_id <= SOULSILVER),
       _plat(game_id == PLATINUM),
       _hgss(game_id == HEARTGOLD or game_id == SOULSILVER)
    {
        _native_pc = reinterpret_cast<void*>(new pksav_nds_pc_pokemon_t);
        *NDS_PC_RCAST = pc;
        _our_pc_mem = true;

        _native_party = reinterpret_cast<void*>(new pksav_nds_pokemon_party_data_t);
        pksav::nds_pc_pokemon_to_party_data(
            _database_entry,
            reinterpret_cast<const pksav_nds_pc_pokemon_t*>(_native_pc),
            reinterpret_cast<pksav_nds_pokemon_party_data_t*>(_native_party)
        );
        _our_party_mem = true;

        // Set _block pointers
        _blockA = &NDS_PC_RCAST->blocks.blockA;
        _blockB = &NDS_PC_RCAST->blocks.blockB;
        _blockC = &NDS_PC_RCAST->blocks.blockC;
        _blockD = &NDS_PC_RCAST->blocks.blockD;

        // Populate abstractions
        _update_held_item();
        _update_ribbons_map();
        _update_EV_map();
        _init_modern_IV_map(&_blockB->iv_isegg_isnicknamed);
        _init_contest_stat_map(&_blockA->contest_stats);
        _init_markings_map(&_blockA->markings);
        _update_stat_map();
        _update_moves(-1);
    }

    pokemon_ndsimpl::~pokemon_ndsimpl() {
        if(_our_pc_mem) {
            delete NDS_PC_RCAST;
        }
        if(_our_party_mem) {
            delete NDS_PARTY_RCAST;
        }
    }

    std::string pokemon_ndsimpl::get_nickname() {
        char nickname[11] = {0};
        if(_gen4) {
            PKSAV_CALL(
                pksav_text_from_gen4(
                    _blockC->nickname,
                    nickname,
                    10
                );
            )
        } else {
            PKSAV_CALL(
                pksav_text_from_gen5(
                    _blockC->nickname,
                    nickname,
                    10
                );
            )
        }

        return std::string(nickname);
    }

    // TODO: isnicknamed flag
    void pokemon_ndsimpl::set_nickname(
        const std::string& nickname
    ) {
        if(nickname.size() < 1 or nickname.size() > 10) {
            throw std::invalid_argument(
                      "The nickname length must be 1-10."
                  );
        }

        if(_gen4) {
            PKSAV_CALL(
                pksav_text_to_gen4(
                    nickname.c_str(),
                    _blockC->nickname,
                    10
                );
            )
        } else {
            PKSAV_CALL(
                pksav_text_to_gen5(
                    nickname.c_str(),
                    _blockC->nickname,
                    10
                );
            )
        }
    }

    bool pokemon_ndsimpl::is_shiny() {
        pokemon_scoped_lock lock(this);

        return pkmn::calculations::modern_shiny(
                   pksav_littleendian32(NDS_PC_RCAST->personality),
                   pksav_littleendian32(_blockA->ot_id.id)
               );
    }

    void pokemon_ndsimpl::set_shininess(
        bool value
    ) {
        pokemon_scoped_lock lock(this);

        _set_modern_shininess(
            &NDS_PC_RCAST->personality,
            &_blockA->ot_id.id,
            value
        );
    }

    void pokemon_ndsimpl::set_held_item(
        const std::string& held_item
    ) {
        // Make sure item is valid and holdable
        pkmn::database::item_entry item(
            held_item,
            get_game()
        );

        if(not item.holdable()) {
            throw std::invalid_argument("This item is not holdable.");
        }

        pokemon_scoped_lock lock(this);

        _blockA->held_item = pksav_littleendian16(uint16_t(item.get_item_index()));

        _update_held_item();
    }

    std::string pokemon_ndsimpl::get_original_trainer_name() {
        char otname[8] = {0};
        if(_gen4) {
            PKSAV_CALL(
                pksav_text_from_gen4(
                    _blockD->otname,
                    otname,
                    7
                );
            )
        } else {
            PKSAV_CALL(
                pksav_text_from_gen5(
                    _blockD->otname,
                    otname,
                    7
                );
            )
        }

        return std::string(otname);
    }

    void pokemon_ndsimpl::set_original_trainer_name(
        const std::string& trainer_name
    ) {
        if(trainer_name.size() < 1 or trainer_name.size() > 7) {
            throw std::invalid_argument(
                      "The trainer name name length must be 1-7."
                  );
        }

        if(_gen4) {
            PKSAV_CALL(
                pksav_text_to_gen4(
                    trainer_name.c_str(),
                    _blockD->otname,
                    7
                );
            )
        } else {
            PKSAV_CALL(
                pksav_text_to_gen5(
                    trainer_name.c_str(),
                    _blockD->otname,
                    7
                );
            )
        }
    }

    uint16_t pokemon_ndsimpl::get_original_trainer_public_id() {
        return pksav_littleendian16(_blockA->ot_id.pid);
    }

    uint16_t pokemon_ndsimpl::get_original_trainer_secret_id() {
        return pksav_littleendian16(_blockA->ot_id.sid);
    }

    uint32_t pokemon_ndsimpl::get_original_trainer_id() {
        return pksav_littleendian32(_blockA->ot_id.id);
    }

    void pokemon_ndsimpl::set_original_trainer_public_id(
        uint16_t public_id
    ) {
        _blockA->ot_id.pid = pksav_littleendian16(public_id);
    }

    void pokemon_ndsimpl::set_original_trainer_secret_id(
        uint16_t secret_id
    ) {
        _blockA->ot_id.sid = pksav_littleendian16(secret_id);
    }

    void pokemon_ndsimpl::set_original_trainer_id(
        uint32_t id
    ) {
        _blockA->ot_id.id = pksav_littleendian32(id);
    }

    std::string pokemon_ndsimpl::get_original_trainer_gender() {
        return (_blockD->metlevel_otgender & PKSAV_NDS_OTGENDER_MASK) ? "Female"
                                                                      : "Male";
    }

    void pokemon_ndsimpl::set_original_trainer_gender(
        const std::string& gender
    ) {
        if(gender == "Male") {
            _blockD->metlevel_otgender &= ~PKSAV_NDS_OTGENDER_MASK;
        } else if(gender == "Female") {
            _blockD->metlevel_otgender |= PKSAV_NDS_OTGENDER_MASK;
        } else {
            throw std::invalid_argument("gender: valid values \"Male\", \"Female\"");
        }
    }

    int pokemon_ndsimpl::get_current_trainer_friendship() {
        pokemon_scoped_lock lock(this);

        return _blockA->friendship;
    }

    void pokemon_ndsimpl::set_current_trainer_friendship(
        int friendship
    ) {
        if(friendship < 0 or friendship > 255) {
            pkmn::throw_out_of_range("friendship", 0, 255);
        }

        pokemon_scoped_lock lock(this);

        _blockA->friendship = uint8_t(friendship);
    }

    std::string pokemon_ndsimpl::get_ability() {
        return pkmn::database::ability_id_to_name(_blockA->ability);
    }

    void pokemon_ndsimpl::set_ability(
        const std::string& ability
    ) {
        std::pair<std::string, std::string> abilities = _database_entry.get_abilities();

        if(ability == "None") {
            throw std::invalid_argument("The ability cannot be set to None.");
        } else if(ability == abilities.first || ability == abilities.second) {
            _blockA->ability = uint8_t(pkmn::database::ability_name_to_id(ability));
        } else {
            std::string error_message;
            if(abilities.second == "None") {
                error_message = str(boost::format("ability: valid values \"%s\"")
                                    % abilities.first.c_str());
            } else {
                error_message = str(boost::format("ability: valid values \"%s\", \"%s\"")
                                    % abilities.first.c_str()
                                    % abilities.second.c_str());
            }

            throw std::invalid_argument(error_message.c_str());
        }
    }

    std::string pokemon_ndsimpl::get_ball() {
        return pkmn::database::ball_id_to_name(
                   _hgss ? _blockD->ball_hgss
                         : _blockD->ball
               );
    }

    void pokemon_ndsimpl::set_ball(
        const std::string& ball
    ) {
        (_hgss ? _blockD->ball_hgss : _blockD->ball) = uint8_t(pkmn::database::ball_name_to_id(
                                                                   ball
                                                               ));
    }

    int pokemon_ndsimpl::get_level_met() {
        pokemon_scoped_lock lock(this);

        return (_blockD->metlevel_otgender & PKSAV_NDS_LEVELMET_MASK);
    }

    void pokemon_ndsimpl::set_level_met(
        int level
    ) {
        if(level < 0 or level > 100) {
            pkmn::throw_out_of_range("Level caught", 0, 100);
        }

        pokemon_scoped_lock lock(this);

        _blockD->metlevel_otgender &= ~PKSAV_NDS_LEVELMET_MASK;
        _blockD->metlevel_otgender |= uint16_t(level);
    }

    std::string pokemon_ndsimpl::get_location_met(
        bool as_egg
    ) {
        return pkmn::database::location_index_to_name(
                   pksav_littleendian16(_plat ? as_egg ? _blockB->eggmet_plat
                                                       : _blockB->met_plat
                                              : as_egg ? _blockD->eggmet_dp
                                                       : _blockD->met_dp
                                       ),
                   _database_entry.get_game_id()
               );
    }

    void pokemon_ndsimpl::set_location_met(
        const std::string& location,
        bool as_egg
    ) {
        uint16_t* field = _plat ? as_egg ? &_blockB->eggmet_plat
                                         : &_blockB->met_plat
                                : as_egg ? &_blockD->eggmet_dp
                                         : &_blockD->met_dp;

        *field = pksav_littleendian16(uint16_t(
                     pkmn::database::location_name_to_index(
                         location,
                         _database_entry.get_game_id()
                     )
                 ));
    }

    std::string pokemon_ndsimpl::get_original_game() {
        return pkmn::database::game_index_to_name(_blockC->hometown);
    }

    void pokemon_ndsimpl::set_original_game(
        const std::string& game
    ) {
        _blockC->hometown = uint8_t(pkmn::database::game_name_to_index(game));
    }

    uint32_t pokemon_ndsimpl::get_personality() {
        return pksav_littleendian32(NDS_PC_RCAST->personality);
    }

    // TODO: automatically update personality-based stuff
    void pokemon_ndsimpl::set_personality(
        uint32_t personality
    ) {
        NDS_PC_RCAST->personality = pksav_littleendian32(personality);
    }

    int pokemon_ndsimpl::get_experience() {
        return int(pksav_littleendian32(_blockA->exp));
    }

    void pokemon_ndsimpl::set_experience(
        int experience
    ) {
        int max_experience = _database_entry.get_experience_at_level(100);

        if(experience < 0 or experience > max_experience) {
            pkmn::throw_out_of_range("experience", 0, max_experience);
        }

        _blockA->exp = pksav_littleendian32(uint32_t(experience));
        NDS_PARTY_RCAST->level = uint8_t(_database_entry.get_level_at_experience(experience));

        _populate_party_data();
        _update_stat_map();
    }

    int pokemon_ndsimpl::get_level() {
        return int(NDS_PARTY_RCAST->level);
    }

    void pokemon_ndsimpl::set_level(
        int level
    ) {
        if(level < 0 or level > 100) {
            pkmn::throw_out_of_range("level", 0, 100);
        }

        NDS_PARTY_RCAST->level = uint8_t(level);
        _blockA->exp = uint32_t(_database_entry.get_experience_at_level(level));

        _populate_party_data();
        _update_stat_map();
    }

    void pokemon_ndsimpl::set_IV(
        const std::string& stat,
        int value
    ) {
        _set_modern_IV(
            stat,
            value,
            &_blockB->iv_isegg_isnicknamed
        );
    }

    void pokemon_ndsimpl::set_marking(
        const std::string& marking,
        bool value
    ) {
        _set_marking(
            marking,
            value,
            &_blockA->markings
        );
    }

    void pokemon_ndsimpl::set_ribbon(
        PKMN_UNUSED(const std::string& ribbon),
        PKMN_UNUSED(bool value)
    ) {
        throw pkmn::unimplemented_error();
    }

    void pokemon_ndsimpl::set_contest_stat(
        const std::string& stat,
        int value
    ) {
        _set_contest_stat(
            stat,
            value,
            &_blockA->contest_stats
        );
    }

    void pokemon_ndsimpl::set_move(
        const std::string& move,
        int index
    ) {
        if(index < 0 or index > 3) {
            pkmn::throw_out_of_range("index", 0, 3);
        }

        // This will throw an error if the move is invalid
        _moves[index].move = pkmn::database::move_entry(
                                 move,
                                 get_game()
                             );
        _moves[index].pp = _moves[index].move.get_pp(0);

        _blockB->moves[index] = uint8_t(_moves[index].move.get_move_id());
        _blockB->move_pps[index] = uint8_t(_moves[index].pp);
    }

    void pokemon_ndsimpl::_populate_party_data() {
        pksav::nds_pc_pokemon_to_party_data(
            _database_entry,
            reinterpret_cast<const pksav_nds_pc_pokemon_t*>(_native_pc),
            reinterpret_cast<pksav_nds_pokemon_party_data_t*>(_native_party)
        );
    }

    void pokemon_ndsimpl::set_EV(
        const std::string& stat,
        int value
    ) {
        if(not pkmn_string_is_modern_stat(stat.c_str())) {
            throw std::invalid_argument("Invalid stat.");
        } else if(not pkmn::EV_in_bounds(value, true)) {
            throw std::out_of_range("Invalid stat.");
        }

        if(stat == "HP") {
            _blockA->ev_hp = uint8_t(value);
        } else if(stat == "Attack") {
            _blockA->ev_atk = uint8_t(value);
        } else if(stat == "Defense") {
            _blockA->ev_def = uint8_t(value);
        } else if(stat == "Speed") {
            _blockA->ev_spd = uint8_t(value);
        } else if(stat == "Special Attack") {
            _blockA->ev_spatk = uint8_t(value);
        } else {
            _blockA->ev_spdef = uint8_t(value);
        }

        _update_EV_map();
        _populate_party_data();
    }

    void pokemon_ndsimpl::_update_moves(
        int index
    ) {
        _moves.reserve(4);
        switch(index) {
            case 0:
            case 1:
            case 2:
            case 3:
                _moves[index] = pkmn::move_slot(
                    pkmn::database::move_entry(
                        pksav_littleendian16(_blockB->moves[index]),
                        _database_entry.get_game_id()
                    ),
                    pksav_littleendian16(_blockB->move_pps[index])
                );
                break;

            default:
                for(int i = 0; i < 4; ++i) {
                    _update_moves(i);
                }
        }
    }

    void pokemon_ndsimpl::_update_held_item() {
        if(int(pksav_littleendian16(_blockA->held_item)) != _held_item.get_item_index()) {
            _held_item = pkmn::database::item_entry(
                             pksav_littleendian16(_blockA->held_item),
                             _database_entry.get_game_id()
                         );
        }
    }

    void pokemon_ndsimpl::_update_ribbons_map() {
        throw pkmn::unimplemented_error();
    }

    void pokemon_ndsimpl::_update_EV_map() {
        _EVs["HP"]              = int(_blockA->ev_hp);
        _EVs["Attack"]          = int(_blockA->ev_atk);
        _EVs["Defense"]         = int(_blockA->ev_def);
        _EVs["Speed"]           = int(_blockA->ev_spd);
        _EVs["Special Attack"]  = int(_blockA->ev_spatk);
        _EVs["Special Defense"] = int(_blockA->ev_spdef);
    }

    void pokemon_ndsimpl::_update_stat_map() {
        _stats["HP"]              = int(pksav_littleendian16(NDS_PARTY_RCAST->max_hp));
        _stats["Attack"]          = int(pksav_littleendian16(NDS_PARTY_RCAST->atk));
        _stats["Defense"]         = int(pksav_littleendian16(NDS_PARTY_RCAST->def));
        _stats["Speed"]           = int(pksav_littleendian16(NDS_PARTY_RCAST->spd));
        _stats["Special Attack"]  = int(pksav_littleendian16(NDS_PARTY_RCAST->spatk));
        _stats["Special Defense"] = int(pksav_littleendian16(NDS_PARTY_RCAST->spdef));
    }
}

max_stars_repo_name: ncorgan/libpkmn

max_issues_repo_name: PMArkive/libpkmn

max_forks_repo_name: PMArkive/libpkmn


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

#include <boost/hana/type.hpp>

#include <boost/hana/sandbox/detail/is_valid.hpp>

#include <type_traits>
using namespace boost::hana;

struct x1; struct x2; struct x3;

template <template <typename ...> class f>
void test() {
    // make sure the types are good
    static_assert(std::is_same<decltype(trait<f>()), f<>>{}, "");
    static_assert(std::is_same<decltype(trait<f>(type<x1>)), f<x1>>{}, "");
    static_assert(std::is_same<decltype(trait<f>(type<x1>, type<x2>)), f<x1, x2>>{}, "");
    static_assert(std::is_same<decltype(trait<f>(type<x1>, type<x2>, type<x3>)), f<x1, x2, x3>>{}, "");

    // make sure we can use it; we already made sure the return type was correct
    trait<f>();
    trait<f>(type<x1>);
    trait<f>(type<x1>, type<x2>);
    trait<f>(type<x1>, type<x2>, type<x3>);
}

template <typename ...> struct f { };
template <typename ...> struct invalid;

template <typename x = void, typename y = void, typename z = void>
using alias = f<x, y, z>;

int main() {
    test<f>();

    // test<alias>();
    // BOOST_HANA_CONSTANT_ASSERT(!detail::is_valid(trait<invalid>)(type<x1>));
}

max_stars_repo_name: rbock/hana

max_issues_repo_name: rbock/hana

max_forks_repo_name: rbock/hana


text:
#include <dai/emalg.h>
#include <iostream>
#include <fstream>
#include <string>
#include <unistd.h>
#include <dai/alldai.h>
#include <boost/thread/thread.hpp>
#include <stdlib.h>
#include <vector>
#include "dai/emrun.h"

using namespace std;
using namespace dai;
using namespace boost;

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

  const  string alarmfgloc = "/home/priya/libDAI-0.3.1/alarm_factor_graphs/";
  const string alarmlearnedfgloc = "/home/priya/libDAI-0.3.1/alarm_learned_factor_graphs/";
  const char* gibbsfile = "/home/priya/libDAI-0.3.1/alarm/1000/23.tab";
  /*const char* fglearnedfileloc1 = "/home/priya/libDAI-0.3.1/alarm_learned_factor_graphs/alarm_5.fg";
  const char* fglearnedfileloc2 = "/home/priya/libDAI-0.3.1/alarm_learned_factor_graphs/alarm_7.fg";
  string fgfileloc1 =  alarmfgloc + "alarm_0.fg";
  string fgfileloc2 =  alarmfgloc + "alarm_1.fg";
  const char* fgfile1 = &fgfileloc1[0];
  const char* fgfile2 = &fgfileloc2[0];*/
  //EMRun* runname;
  vector <EMRun*> layer;
  int pop_size=5;
  size_t i =0,j=0;
  size_t maxIters = 100;
  while(i<pop_size)
  {
	 string number;
	 stringstream num;
	 num << i;
	 number = num.str();
	 string fgfileloc =  alarmfgloc + "/"+"alarm_"+number+".fg";
	 const char* fgfile = &fgfileloc[0];

	 EMRun* runname = new EMRun("alarm", i, fgfile, gibbsfile); // args are -1.network name 2.factor-graph number 3. evidencefile

	 // 2. Run EM
	 boost::thread threadid(boost::bind(&EMRun::startEM, boost::ref(runname), maxIters)); // args - max iters
	 layer.push_back(runname);
	 sleep(1);
	 // 4. Next individual
	 i=i+1;
 }
while (true){
	   // cout<<"in while loop "<<layer.size()<<endl;
	    vector<EMRun*>::iterator it;
	    for (it=layer.begin(); it != layer.end(); ++it){
	      //cout<<"layer size "<<layer.size()<<endl;
	      if((*it)->hasTerminated()) { //if it has terminated, set the run aside
		double ll = (*it)->getLL();
		double iters = (*it)->getIters();
		double runid = (*it)->getRun();
		string number;
		stringstream num;
		num << runid;
		number = num.str();
	 	string fglearnedfileloc =  alarmlearnedfgloc + "alarm_"+number+".fg";
	    	const char* fglearnedfile = &fglearnedfileloc[0];
		cout<<"Run number "<<number<<" ll = "<<ll<<" iters = "<<iters<<endl;
		// 3. Store the learned factor graphs
		InfAlg* inf = (*it)->getInf();
		ofstream learnedstream;
		/*cout<<"learned file = "<<fglearnedfile<<endl;
		learnedstream.open(fglearnedfile);
		learnedstream.precision(12);
		learnedstream << inf->fg();
		learnedstream.flush();
		learnedstream.close();*/
		delete inf;
		sleep(1);
		//cout<<"Run number "<<number<<" has terminated"<<endl;
		//out<<gibbsfile<<" "<<fglearnedfile<<" "<<runid<<" "<<iters<<" "<<ll<<" "<<endl;
		layer.erase(it);
		if (layer.size() == 0){break;}
		else { it = layer.begin(); }
	      }
	      else
		{
		}
	}
	if (layer.size() == 0){break;}
}
  //EMRun* testrun2 = new EMRun("alarm", 1, fgfile2, gibbsfile);

 /* EMRun* testrun3 = new EMRun("alarm", 13, gibbsfile);
  EMRun* testrun4 = new EMRun("alarm", 32, gibbsfile);

  boost::thread thread1(boost::bind(&EMRun::startEM, boost::ref(testrun), 100));
  boost::thread thread2(boost::bind(&EMRun::startEM, boost::ref(testrun2), 100));
 /* boost::thread thread3(boost::bind(&EMRun::startEM, boost::ref(testrun3), 100));
  boost::thread thread4(boost::bind(&EMRun::startEM, boost::ref(testrun4), 100)); */
//  sleep(10);
 // boost::thread thread9(boost::bind(&EMRun::stopEM, boost::ref(testrun)));
 // boost::thread thread5(boost::bind(&EMRun::stopEM, boost::ref(testrun2)));
/* boost::thread thread6(boost::bind(&EMRun::stopEM, boost::ref(testrun3)));
  boost::thread thread7(boost::bind(&EMRun::stopEM, boost::ref(testrun4)));
  double ll1 = testrun->getLL();
  double iters1 = testrun->getIters();
  double ll2 = testrun2->getLL();
  double iters2 = testrun2->getIters();
  InfAlg *inf_1 = testrun->getInf();
  InfAlg *inf_2 = testrun2->getInf();
  ofstream learnedstream1;
      cout<<"learned file = "<<fglearnedfileloc1;
      learnedstream1.open(fglearnedfileloc1);
      learnedstream1.precision(12);
      learnedstream1 << inf_1->fg();
      learnedstream1.close();
 ofstream learnedstream2;
      cout<<"learned file = "<<fglearnedfileloc2;
      learnedstream2.open(fglearnedfileloc2);
      learnedstream2.precision(12);
      learnedstream2 << inf_2->fg();
      learnedstream2.close();

  cout<<"Stopping testrun.."<<endl;
  cout << "LL for testrun eventually " <<ll1<<endl;
  cout << "iterations for testrun eventually "<<iters1<<endl;
 cout<<"Stopping testrun2.."<<endl;
  cout << "LL for testrun2 eventually " <<ll2<<endl;
  cout << "iterations for testrun2 eventually "<<iters2<<endl;
 /*vector <EMRun*> layer2;
  vector <EMRun*> layer2_finalval;

  layer2.push_back(testrun3);
  layer2.push_back(testrun4);

  boost::thread thread1(boost::bind(&EMRun::startEM, boost::ref(testrun), 100));
  boost::thread thread2(boost::bind(&EMRun::startEM, boost::ref(testrun2), 100));
  cout <<"Started older layer, consisting of factor graphs "<< testrun->getRun() << " and " << testrun2->getRun() << endl;

  int seconds = atoi (argv[1]);
  sleep(seconds);

  const int maxIters = 10;
  boost::thread thread3(boost::bind(&EMRun::startEM, boost::ref(testrun3), maxIters));
  boost::thread thread4(boost::bind(&EMRun::startEM, boost::ref(testrun4), maxIters));
  cout <<"Started younger layer consisting of factor graphs "<< testrun3->getRun() << " and " << testrun4->getRun() <<endl;

  while (true){
    vector<EMRun*>::iterator it;
    for (it=layer2.begin(); it != layer2.end(); ++it){
      if((*it)->hasTerminated()) { //if it has terminated, set the run aside
	cout<<"Run number "<<(*it)->getRun()<<" has terminated"<<endl;
	layer2_finalval.push_back(*it);
	layer2.erase(it);
	if (layer2.size() == 0){break;}
	else { it = layer2.begin(); }
      }
      if ((*it)->getIters() == maxIters){ //we stop the ones in the higher layer - in reality, we can have a function that loops through a layer and stops everything
	cout<<"Run number "<<(*it)->getRun()<<" has reached the maximum iterations"<<endl;
	int numit = (*it)->getIters();
	cout<<"The number of iterations it has undergone is "<<numit<<endl;
	boost::thread thread5(boost::bind(&EMRun::stopEM, boost::ref(testrun)));
	boost::thread thread6(boost::bind(&EMRun::stopEM, boost::ref(testrun2)));
	cout<<"Stopped runs in the layer immediately above..."<<endl;
	double ll1 = testrun->getLL();
	double ll2 = testrun2->getLL();
	double ll_test = (*it)->getLL();
	cout << "LL values in higher layer are "<< ll1 << " and "<< ll2 << endl;
	cout<< "LL value for recently finished run in lower layer is " << ll_test << endl;
	layer2.erase(it);
	if (layer2.size() == 0) { break; }
	else {	it = layer2.begin(); }
	cout<<"Size of layer now is "<<layer2.size()<<endl;
	cout<<"Resuming runs in the layer immediately above..."<<endl;
	boost::thread thread7(boost::bind(&EMRun::resumeEM, boost::ref(testrun)));
	boost::thread thread8(boost::bind(&EMRun::resumeEM, boost::ref(testrun2)));
      }
    }
    if (layer2.size() == 0){ break; }
  sleep(1);
  }

  sleep(5);
  cout<<"Waited 5 seconds..."<<endl;

  boost::thread thread9(boost::bind(&EMRun::stopEM, boost::ref(testrun)));
  boost::thread thread10(boost::bind(&EMRun::stopEM, boost::ref(testrun2)));
  cout<<"Stopped testrun and testrun2..."<<endl;
  double ll1 = testrun->getLL();
  double ll2 = testrun2->getLL();
  int iters1 = testrun->getIters();
  int iters2 = testrun2->getIters();
  cout << "LL for testrun1 eventually " <<ll1<<endl;
  cout << "iterations for testrun1 eventually "<<iters1<<endl;
  cout << "LL for testrun2 eventually " <<ll2<<endl;
  cout << "iterations for testrun2 eventually "<<iters2<<endl;

  if (testrun->hasTerminated()){
    cout<<"testrun has terminated..."<<endl;
  }
  if (testrun2->hasTerminated()){
    cout<<"testrun2 has terminated..."<<endl;
  }

  boost::thread thread11(boost::bind(&EMRun::resumeEM, boost::ref(testrun3)));
  boost::thread thread12(boost::bind(&EMRun::startEM, boost::ref(testrun3), 20));
  sleep(seconds);
  cout<<"Waited "<<seconds<<" seconds..."<<endl;
  boost::thread thread13(boost::bind(&EMRun::stopEM, boost::ref(testrun3)));
  ll1 = testrun3->getLL();
  iters1 = testrun3->getIters();
  cout<<"LL and iters for testrun 3 are "<<ll1<<" and "<<iters1<<endl;

  boost::thread thread7(boost::bind(&EMRun::resumeEM, boost::ref(testrun)));
  boost::thread thread8(boost::bind(&EMRun::resumeEM, boost::ref(testrun2)));
  cout<<"Resuming testrun and testrun2..."<<endl;
  sleep(seconds);
  boost::thread thread11(boost::bind(&EMRun::stopEM, boost::ref(testrun)));
  boost::thread thread12(boost::bind(&EMRun::stopEM, boost::ref(testrun2)));
  ll1 = testrun->getLL();
  ll2 = testrun2->getLL();
  iters1 = testrun->getIters();
  iters2 = testrun2->getIters();
  cout<<"Stopping testrun and testrun2..."<<endl;
  cout << "LL for testrun1 eventually " <<ll1<<endl;
  cout << "iterations for testrun1 eventually "<<iters1<<endl;
  cout << "LL for testrun2 eventually " <<ll2<<endl;
  cout << "iterations for testrun2 eventually "<<iters2<<endl;*/

  return 0;
}