<commit_before>#include <Engine/RadiumEngine.hpp>

#include <thread>
#include <chrono>
#include <mutex>
#include <cstdio>
#include <iostream>
#include <fstream>
#include <string>
#include <streambuf>

#include <Core/Log/Log.hpp>
#include <Core/String/StringUtils.hpp>
#include <Core/Event/EventEnums.hpp>
#include <Core/Event/KeyEvent.hpp>
#include <Core/Event/MouseEvent.hpp>
#include <Engine/Entity/FrameInfo.hpp>
#include <Engine/Entity/System.hpp>
#include <Engine/Entity/Component.hpp>
#include <Engine/Entity/Entity.hpp>
#include <Engine/Entity/EntityManager.hpp>

#include <Engine/Assets/FileData.hpp>

#include <Engine/SystemDisplay/SystemDisplay.hpp>

namespace Ra
{
	namespace Engine
	{

		RadiumEngine::RadiumEngine()
		{
				LOG(logINFO) << "*** Radium Engine ***";
		}

		RadiumEngine::~RadiumEngine()
		{
		}

		void RadiumEngine::initialize()
		{
			m_renderObjectManager.reset( new RenderObjectManager );
			m_entityManager.reset( new EntityManager );

			for (std::pair<const std::string, std::shared_ptr<Ra::Engine::System>> systemPair : m_systems)
				systemPair.second->initialize();
		}

		void RadiumEngine::cleanup()
		{
			m_entityManager.reset();
			m_renderObjectManager.reset();

			for ( auto& system : m_systems )
			{
				system.second.reset();
			}
		}

		void RadiumEngine::endFrameSync()
		{
			m_entityManager->swapBuffers();
			m_renderObjectManager->swapBuffers();
		}

		void RadiumEngine::getTasks( Core::TaskQueue* taskQueue,  Scalar dt )
		{
			static uint frameCounter = 0;
			FrameInfo frameInfo;
			frameInfo.m_dt = dt;
			frameInfo.m_numFrame = frameCounter++;
			for ( auto& syst : m_systems )
			{
				syst.second->generateTasks( taskQueue, frameInfo );
			}
		}

		void RadiumEngine::registerSystem( const std::string& name, System* system )
		{
			CORE_ASSERT( m_systems.find( name ) == m_systems.end(),
						 "Same system added multiple times." );

			m_systems[name] = std::shared_ptr<System> ( system );
			LOG(logINFO) << "Loaded : " << name;
		}

		System* RadiumEngine::getSystem( const std::string& system ) const
		{
			System* sys = nullptr;
			auto it = m_systems.find( system );

			if ( it != m_systems.end() )
			{
				sys = it->second.get();
			}

			return sys;
		}

		bool RadiumEngine::loadFile( const std::string& filename )
        {
            Asset::FileData fileData( filename, true );

            std::string entityName = Core::StringUtils::getBaseName( filename, false );

            Entity* entity = m_entityManager->getOrCreateEntity( entityName );

            m_systems["FancyMeshSystem"]->handleAssetLoading( entity, &fileData );
            for ( auto& sys : m_systems )
            {
                if ( sys.first != "FancyMeshSystem" )
                {
                    sys.second->handleAssetLoading( entity, &fileData );
                }
            }

#if 0
			if (Ra::Core::StringUtils::getFileExt(filename) != "json")
			{
				Entity* entity = m_entityManager->createEntity();

//				for ( auto& system : m_systems )
//	            {
//					system.second->handleFileLoading(entity, filename);
//	            }

                // FIXME(Charly): We do not want this hard coded system name
				getSystem("FancyMeshSystem")->handleFileLoading(entity, filename);

				return true;
			}

			// Fill file in a string (http://stackoverflow.com/a/2602060)
			std::ifstream t( filename );
			std::string file;

			t.seekg( 0, std::ios::end );
			file.reserve( t.tellg() );
			t.seekg( 0, std::ios::beg );

			file.assign( ( std::istreambuf_iterator<char>( t ) ),
						 ( std::istreambuf_iterator<char>() ) );
			std::string err;

			std::vector<LoadedEntity> loadedData;
			Parser::parse( file, loadedData );

			LOG( logDEBUG ) << "Found " << loadedData.size() << " entities to load.";

			std::string rootFolder = Core::StringUtils::getDirName( filename );

			for ( const auto& entityData : loadedData )
			{
				Entity* entity = m_entityManager->getOrCreateEntity( entityData.name );
				Core::Transform transform;
                transform.fromPositionOrientationScale( entityData.position,
                                                        entityData.orientation,
                                                        entityData.scale );
				entity->setTransform( transform );

				for ( const auto& systemData : entityData.data )
				{
					auto system = m_systems.find( systemData.system );

					if ( system != m_systems.end() )
					{
						system->second->handleDataLoading( entity, rootFolder, systemData.data );
					}
				}
			}
#endif

			return true;
		}

		bool RadiumEngine::handleKeyEvent( const Core::KeyEvent& event )
		{
			for ( const auto& system : m_systems )
			{
				if ( system.second->handleKeyEvent( event ) )
				{
					return true;
				}
			}

			return false;
		}

		bool RadiumEngine::handleMouseEvent( const Core::MouseEvent& event )
		{
			for ( const auto& system : m_systems )
			{
				if ( system.second->handleMouseEvent( event ) )
				{
					return true;
				}
			}

			return false;
		}

		RenderObjectManager* RadiumEngine::getRenderObjectManager() const
		{
			return m_renderObjectManager.get();
		}

		EntityManager* RadiumEngine::getEntityManager() const
		{
			return m_entityManager.get();
		}

		RA_SINGLETON_IMPLEMENTATION(RadiumEngine)
	} // Namespace engine
} // namespace Ra
<commit_msg>Fix RadiumEngine formatting<commit_after>#include <Engine/RadiumEngine.hpp>

#include <thread>
#include <chrono>
#include <mutex>
#include <cstdio>
#include <iostream>
#include <fstream>
#include <string>
#include <streambuf>

#include <Core/Log/Log.hpp>
#include <Core/String/StringUtils.hpp>
#include <Core/Event/EventEnums.hpp>
#include <Core/Event/KeyEvent.hpp>
#include <Core/Event/MouseEvent.hpp>
#include <Engine/Entity/FrameInfo.hpp>
#include <Engine/Entity/System.hpp>
#include <Engine/Entity/Component.hpp>
#include <Engine/Entity/Entity.hpp>
#include <Engine/Entity/EntityManager.hpp>

#include <Engine/Assets/FileData.hpp>

#include <Engine/Parser/Parser.hpp>
#include <Engine/Parser/LoadedData.hpp>

#include <Engine/SystemDisplay/SystemDisplay.hpp>

namespace Ra
{
	namespace Engine
	{

        RadiumEngine::RadiumEngine()
        {
            LOG(logINFO) << "*** Radium Engine ***";
        }

        RadiumEngine::~RadiumEngine()
        {
        }

        void RadiumEngine::initialize()
        {
            m_renderObjectManager.reset( new RenderObjectManager );
            m_entityManager.reset( new EntityManager );

            for (std::pair<const std::string, std::shared_ptr<Ra::Engine::System>> systemPair : m_systems)
                systemPair.second->initialize();
        }

        void RadiumEngine::cleanup()
        {
            m_entityManager.reset();
            m_renderObjectManager.reset();

            for ( auto& system : m_systems )
            {
                system.second.reset();
            }
        }

        void RadiumEngine::endFrameSync()
        {
            m_entityManager->swapBuffers();
            m_renderObjectManager->swapBuffers();
        }

        void RadiumEngine::getTasks( Core::TaskQueue* taskQueue,  Scalar dt )
        {
            static uint frameCounter = 0;
            FrameInfo frameInfo;
            frameInfo.m_dt = dt;
            frameInfo.m_numFrame = frameCounter++;
            for ( auto& syst : m_systems )
            {
                syst.second->generateTasks( taskQueue, frameInfo );
            }
        }

        void RadiumEngine::registerSystem( const std::string& name, System* system )
        {
            CORE_ASSERT( m_systems.find( name ) == m_systems.end(),
                         "Same system added multiple times." );

            m_systems[name] = std::shared_ptr<System> ( system );
            LOG(logINFO) << "Loaded : " << name;
        }

        System* RadiumEngine::getSystem( const std::string& system ) const
        {
            System* sys = nullptr;
            auto it = m_systems.find( system );

            if ( it != m_systems.end() )
            {
                sys = it->second.get();
            }

            return sys;
        }

        bool RadiumEngine::loadFile( const std::string& filename )
        {
            Asset::FileData fileData( filename, true );

            std::string entityName = Core::StringUtils::getBaseName( filename, false );

            Entity* entity = m_entityManager->getOrCreateEntity( entityName );

            for( auto& system : m_systems ) {
                system.second->handleAssetLoading( entity, &fileData );
            }
            //getSystem("FancyMeshSystem")->handleAssetLoading( entity, &fileData );

            return true;
        }

        bool RadiumEngine::handleKeyEvent( const Core::KeyEvent& event )
        {
            for ( const auto& system : m_systems )
            {
                if ( system.second->handleKeyEvent( event ) )
                {
                    return true;
                }
            }

            return false;
        }

        bool RadiumEngine::handleMouseEvent( const Core::MouseEvent& event )
        {
            for ( const auto& system : m_systems )
            {
                if ( system.second->handleMouseEvent( event ) )
                {
                    return true;
                }
            }

            return false;
        }

        RenderObjectManager* RadiumEngine::getRenderObjectManager() const
        {
            return m_renderObjectManager.get();
        }

        EntityManager* RadiumEngine::getEntityManager() const
        {
            return m_entityManager.get();
        }

        RA_SINGLETON_IMPLEMENTATION(RadiumEngine)
    } // Namespace engine
} // namespace Ra
<|endoftext|>


<commit_before>#pragma once

#include <Utils/OpenGL.hh>
#include <Render/Key.hh>
#include <Render/Buffer.hh>
#include <Render/VertexArray.hh>
#include <Render/Pool.hh>
#include <Utils/Dependency.hpp>
#include <map>
#include <Utils/Containers/Vector.hpp>

namespace gl
{
	class Vertices;

	const uint8_t nbrSimpleForm = 1;

	enum SimpleForm
	{
		QUAD = 0
	};

	class GeometryManager
	{
	public:
		template <typename TYPE, typename POOL>
		struct Attach
		{
			TYPE const *data;
			POOL *pool;
			Key<Pool::Element<TYPE>> element;
		};

	public:
		// constructor
		GeometryManager();
		~GeometryManager();

		GeometryManager &createSimpleForm();
		Key<Vertices> getSimpleForm(SimpleForm form);

		// handle pools
		Key<VertexPool> addVertexPool();
		Key<VertexPool> addVertexPool(uint8_t nbrAttributes, GLenum *typeComponent, uint8_t *sizeTypeComponent, uint8_t *nbrComponent);
		Key<VertexPool> getVertexPool(size_t index) const;
		size_t nbrVertexPool() const;
		GeometryManager &rmVertexPool(Key<VertexPool> &key);
		Key<IndexPool> addIndexPool();
		Key<IndexPool> getIndexPool(size_t index) const;
		size_t nbrIndexPool() const;
		GeometryManager &rmIndexPool(Key<IndexPool> &key);

		//handle Vertices and Indices
		Key<Vertices> addVertices(size_t nbrVertices, uint8_t nbrBuffers, size_t *sizeBuffers, void **buffers);
		Key<Indices> addIndices(size_t nbrIndices, uint32_t *buffers);
		GeometryManager &rmVertices(Key<Vertices> &key);
		GeometryManager &rmIndices(Key<Indices> &key);
		Key<Vertices> getVertices(size_t index) const;
		Key<Indices> getIndices(size_t index) const;
		size_t getNbrVertices() const;
		size_t getNbrIndices() const;

		// attach vertices to pools
		GeometryManager &attachVerticesToVertexPool(Key<Vertices> const &vertices, Key<VertexPool> const &pool);
		GeometryManager &dettachVerticesToVertexPool(Key<Vertices> const &vertices);
		GeometryManager &attachIndicesToIndexPool(Key<Indices> const &vertices, Key<IndexPool> const &pool);
		GeometryManager &dettachIndicesToIndexPool(Key<Indices> const &vertices);
		GeometryManager &attachIndexPoolToVertexPool(Key<VertexPool> const &vertexpool, Key<IndexPool> const &indicespool);
		GeometryManager &dettachIndexPoolToVertexPool(Key<VertexPool> const &vertexpool, Key<IndexPool> const &indexpool);

		// draw
		GeometryManager &draw(GLenum mode, Key<Indices> const &keyindices, Key<Vertices> const &keyVertice);
		GeometryManager &draw(GLenum mode, Key<Vertices> const &keyvertices);

		// generate ico sphere
		static void generateIcoSphere(size_t recursion, glm::vec3 **vertex, glm::u32vec3 **indices);

	private:
		// simple form
		gl::Key<Vertices> *_simpleForm;

		// data represent pools
		std::map<Key<IndexPool>, IndexPool> _indexPool;
		std::map<Key<VertexPool>, VertexPool> _vertexPool;
		std::map<Key<Indices>, Indices>	_indices;
		std::map<Key<Vertices>, Vertices> _vertices;
		std::map<Key<Vertices>, Attach<Vertices, VertexPool>> _vertexAttach;
		std::map<Key<Indices>, Attach<Indices, IndexPool>> _indexAttach;

		std::pair<Key<IndexPool>, IndexPool *> _optimizerIndexPoolSearch;
		std::pair<Key<VertexPool>, VertexPool *> _optimizerVertexPoolSearch;
		std::pair<Key<Vertices>, Vertices *> _optimizerVerticesSearch;
		std::pair<Key<Indices>, Indices *> _optimizerIndicesSearch;
		std::pair<Key<Vertices>, Attach<Vertices, VertexPool> *> _optimizerVertexAttachSearch;
		std::pair<Key<Indices>, Attach<Indices, IndexPool> *> _optimizerIndexAttachSearch;

		// tool use in intern
		VertexPool *getVertexPool(Key<VertexPool> const &key, std::string const &in);
		IndexPool *getIndexPool(Key<IndexPool> const &key, std::string const &in);
		Indices *getIndices(Key<Indices> const &key, std::string const &in);
		Vertices *getVertices(Key<Vertices> const &key, std::string const &in);
		Attach<Vertices, VertexPool> *getVertexAttach(Key<Vertices> const &key, std::string const &in);
		Attach<Indices, IndexPool> *getIndexAttach(Key<Indices> const &key, std::string const &in);
	};
}<commit_msg>added glm include<commit_after>#pragma once

#include <Utils/OpenGL.hh>
#include <Render/Key.hh>
#include <Render/Buffer.hh>
#include <Render/VertexArray.hh>
#include <Render/Pool.hh>
#include <Utils/Dependency.hpp>
#include <map>
#include <Utils/Containers/Vector.hpp>
#include <glm/glm.hpp>

namespace gl
{
	class Vertices;

	const uint8_t nbrSimpleForm = 1;

	enum SimpleForm
	{
		QUAD = 0
	};

	class GeometryManager
	{
	public:
		template <typename TYPE, typename POOL>
		struct Attach
		{
			TYPE const *data;
			POOL *pool;
			Key<Pool::Element<TYPE>> element;
		};

	public:
		// constructor
		GeometryManager();
		~GeometryManager();

		GeometryManager &createSimpleForm();
		Key<Vertices> getSimpleForm(SimpleForm form);

		// handle pools
		Key<VertexPool> addVertexPool();
		Key<VertexPool> addVertexPool(uint8_t nbrAttributes, GLenum *typeComponent, uint8_t *sizeTypeComponent, uint8_t *nbrComponent);
		Key<VertexPool> getVertexPool(size_t index) const;
		size_t nbrVertexPool() const;
		GeometryManager &rmVertexPool(Key<VertexPool> &key);
		Key<IndexPool> addIndexPool();
		Key<IndexPool> getIndexPool(size_t index) const;
		size_t nbrIndexPool() const;
		GeometryManager &rmIndexPool(Key<IndexPool> &key);

		//handle Vertices and Indices
		Key<Vertices> addVertices(size_t nbrVertices, uint8_t nbrBuffers, size_t *sizeBuffers, void **buffers);
		Key<Indices> addIndices(size_t nbrIndices, uint32_t *buffers);
		GeometryManager &rmVertices(Key<Vertices> &key);
		GeometryManager &rmIndices(Key<Indices> &key);
		Key<Vertices> getVertices(size_t index) const;
		Key<Indices> getIndices(size_t index) const;
		size_t getNbrVertices() const;
		size_t getNbrIndices() const;

		// attach vertices to pools
		GeometryManager &attachVerticesToVertexPool(Key<Vertices> const &vertices, Key<VertexPool> const &pool);
		GeometryManager &dettachVerticesToVertexPool(Key<Vertices> const &vertices);
		GeometryManager &attachIndicesToIndexPool(Key<Indices> const &vertices, Key<IndexPool> const &pool);
		GeometryManager &dettachIndicesToIndexPool(Key<Indices> const &vertices);
		GeometryManager &attachIndexPoolToVertexPool(Key<VertexPool> const &vertexpool, Key<IndexPool> const &indicespool);
		GeometryManager &dettachIndexPoolToVertexPool(Key<VertexPool> const &vertexpool, Key<IndexPool> const &indexpool);

		// draw
		GeometryManager &draw(GLenum mode, Key<Indices> const &keyindices, Key<Vertices> const &keyVertice);
		GeometryManager &draw(GLenum mode, Key<Vertices> const &keyvertices);

		// generate ico sphere
		static void generateIcoSphere(size_t recursion, glm::vec3 **vertex, glm::u32vec3 **indices);

	private:
		// simple form
		gl::Key<Vertices> *_simpleForm;

		// data represent pools
		std::map<Key<IndexPool>, IndexPool> _indexPool;
		std::map<Key<VertexPool>, VertexPool> _vertexPool;
		std::map<Key<Indices>, Indices>	_indices;
		std::map<Key<Vertices>, Vertices> _vertices;
		std::map<Key<Vertices>, Attach<Vertices, VertexPool>> _vertexAttach;
		std::map<Key<Indices>, Attach<Indices, IndexPool>> _indexAttach;

		std::pair<Key<IndexPool>, IndexPool *> _optimizerIndexPoolSearch;
		std::pair<Key<VertexPool>, VertexPool *> _optimizerVertexPoolSearch;
		std::pair<Key<Vertices>, Vertices *> _optimizerVerticesSearch;
		std::pair<Key<Indices>, Indices *> _optimizerIndicesSearch;
		std::pair<Key<Vertices>, Attach<Vertices, VertexPool> *> _optimizerVertexAttachSearch;
		std::pair<Key<Indices>, Attach<Indices, IndexPool> *> _optimizerIndexAttachSearch;

		// tool use in intern
		VertexPool *getVertexPool(Key<VertexPool> const &key, std::string const &in);
		IndexPool *getIndexPool(Key<IndexPool> const &key, std::string const &in);
		Indices *getIndices(Key<Indices> const &key, std::string const &in);
		Vertices *getVertices(Key<Vertices> const &key, std::string const &in);
		Attach<Vertices, VertexPool> *getVertexAttach(Key<Vertices> const &key, std::string const &in);
		Attach<Indices, IndexPool> *getIndexAttach(Key<Indices> const &key, std::string const &in);
	};
}<|endoftext|>


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

/// \file
/// Tests for the VisualizeContactsBehavior class.

#include <gtest/gtest.h>
#include <yaml-cpp/yaml.h>

#include "SurgSim/Blocks/VisualizeContactsBehavior.h"
#include "SurgSim/Physics/RigidCollisionRepresentation.h"
#include "SurgSim/Framework/FrameworkConvert.h"

using SurgSim::Blocks::VisualizeContactsBehavior;
using SurgSim::Physics::RigidCollisionRepresentation;
using YAML::Node;

TEST(VisualizeContactsBehaviorTests, Constructor)
{
	EXPECT_NO_THROW(std::make_shared<VisualizeContactsBehavior>("VisualizeContactsBehavior"));
	EXPECT_NO_THROW({ VisualizeContactsBehavior visualizeContactsBehavior("VisualizeContactsBehavior"); });
}

TEST(VisualizeContactsBehaviorTests, SettersGetters)
{
	auto visualizeContactsBehavior = std::make_shared<VisualizeContactsBehavior>("VisualizeContactsBehavior");

	// Test collision representation.
	std::string name = "CollisionRepresentation";
	auto collisionRepresentaiton = std::make_shared<RigidCollisionRepresentation>(name);

	EXPECT_NO_THROW(visualizeContactsBehavior->setCollisionRepresentation(collisionRepresentaiton));
	EXPECT_EQ(name, visualizeContactsBehavior->getCollisionRepresentation()->getName());

	// Test vector field scale.
	EXPECT_ANY_THROW(visualizeContactsBehavior->setVectorFieldScale(-1.023));

	double scale = 1.234;
	EXPECT_NO_THROW(visualizeContactsBehavior->setVectorFieldScale(scale));
	EXPECT_EQ(scale, visualizeContactsBehavior->getVectorFieldScale());
}

TEST(VisualizeContactsBehaviorTests, Serialization)
{
	auto visualizeContactsBehavior = std::make_shared<VisualizeContactsBehavior>("VisualizeContactsBehavior");
	std::string name = "CollisionRepresentation";
	auto collisionRepresentaiton = std::make_shared<RigidCollisionRepresentation>(name);
	EXPECT_NO_THROW(visualizeContactsBehavior->setCollisionRepresentation(collisionRepresentaiton));
	double scale = 1.234;
	EXPECT_NO_THROW(visualizeContactsBehavior->setVectorFieldScale(scale));

	// Encode
	Node node;
	EXPECT_NO_THROW(node = YAML::convert<SurgSim::Framework::Component>::encode(*visualizeContactsBehavior));
	EXPECT_TRUE(node.IsMap());

	// Decode
	std::shared_ptr<VisualizeContactsBehavior> newVisualizeContactsBehavior;
	EXPECT_NO_THROW(newVisualizeContactsBehavior = std::dynamic_pointer_cast<VisualizeContactsBehavior>(
		node.as<std::shared_ptr<SurgSim::Framework::Component>>()));

	// Verify
	EXPECT_EQ(name, newVisualizeContactsBehavior->getCollisionRepresentation()->getName());
	EXPECT_EQ(scale, newVisualizeContactsBehavior->getVectorFieldScale());
}<commit_msg>Updated Serialization test to use accessors.<commit_after>// This file is a part of the OpenSurgSim project.
// Copyright 2013, SimQuest Solutions Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/// \file
/// Tests for the VisualizeContactsBehavior class.

#include <gtest/gtest.h>
#include <yaml-cpp/yaml.h>

#include "SurgSim/Blocks/VisualizeContactsBehavior.h"
#include "SurgSim/Physics/RigidCollisionRepresentation.h"
#include "SurgSim/Framework/FrameworkConvert.h"

using SurgSim::Blocks::VisualizeContactsBehavior;
using SurgSim::Physics::RigidCollisionRepresentation;
using YAML::Node;

TEST(VisualizeContactsBehaviorTests, Constructor)
{
	EXPECT_NO_THROW(std::make_shared<VisualizeContactsBehavior>("VisualizeContactsBehavior"));
	EXPECT_NO_THROW({ VisualizeContactsBehavior visualizeContactsBehavior("VisualizeContactsBehavior"); });
}

TEST(VisualizeContactsBehaviorTests, SettersGetters)
{
	auto visualizeContactsBehavior = std::make_shared<VisualizeContactsBehavior>("VisualizeContactsBehavior");

	// Test collision representation.
	std::string name = "CollisionRepresentation";
	auto collisionRepresentaiton = std::make_shared<RigidCollisionRepresentation>(name);

	EXPECT_NO_THROW(visualizeContactsBehavior->setCollisionRepresentation(collisionRepresentaiton));
	EXPECT_EQ(name, visualizeContactsBehavior->getCollisionRepresentation()->getName());

	// Test vector field scale.
	EXPECT_ANY_THROW(visualizeContactsBehavior->setVectorFieldScale(-1.023));

	double scale = 1.234;
	EXPECT_NO_THROW(visualizeContactsBehavior->setVectorFieldScale(scale));
	EXPECT_EQ(scale, visualizeContactsBehavior->getVectorFieldScale());
}

TEST(VisualizeContactsBehaviorTests, Serialization)
{
	auto visualizeContactsBehavior = std::make_shared<VisualizeContactsBehavior>("VisualizeContactsBehavior");
	std::string name = "CollisionRepresentation";
	auto collisionRepresentation = std::make_shared<RigidCollisionRepresentation>(name);
	EXPECT_NO_THROW(visualizeContactsBehavior->setValue("CollisionRepresentation",
		std::static_pointer_cast<SurgSim::Framework::Component>(collisionRepresentation)););
	double scale = 1.234;
	EXPECT_NO_THROW(visualizeContactsBehavior->setValue("VectorFieldScale", scale));
	EXPECT_EQ("SurgSim::Blocks::VisualizeContactsBehavior", visualizeContactsBehavior->getClassName());

	// Encode
	Node node;
	EXPECT_NO_THROW(node = YAML::convert<SurgSim::Framework::Component>::encode(*visualizeContactsBehavior));
	EXPECT_TRUE(node.IsMap());
	EXPECT_EQ(4, node[visualizeContactsBehavior->getClassName()].size());

	// Decode
	std::shared_ptr<VisualizeContactsBehavior> newVisualizeContactsBehavior;
	EXPECT_NO_THROW(newVisualizeContactsBehavior = std::dynamic_pointer_cast<VisualizeContactsBehavior>(
		node.as<std::shared_ptr<SurgSim::Framework::Component>>()));

	// Verify
	EXPECT_EQ(name, SurgSim::Framework::convert<std::shared_ptr<SurgSim::Framework::Component>>(
					newVisualizeContactsBehavior->getValue("CollisionRepresentation"))->getName());
	EXPECT_EQ(scale, SurgSim::Framework::convert<double>(newVisualizeContactsBehavior->getValue("VectorFieldScale")));
}<|endoftext|>


<commit_before>#pragma once

#include "Communicator.hpp"
#include "CompletionEvent.hpp"
#include "Tasking.hpp"
#include "Message.hpp"
#include "MessagePool.hpp"
#include "Delegate.hpp"
#include "Collective.hpp"
#include "Timestamp.hpp"
#include <type_traits>
#include "Statistics.hpp"

#define PRINT_MSG(m) "msg(" << &(m) << ", src:" << (m).source_ << ", dst:" << (m).destination_ << ", enq:" << (m).is_enqueued_ << ", sent:" << (m).is_sent_ << ", deliv:" << (m).is_delivered_ << ")"

DECLARE_bool( flatten_completions );

/// total number of times "complete" has to be called on another core
GRAPPA_DECLARE_STAT(SimpleStatistic<uint64_t>, gce_total_remote_completions);

/// actual number of completion messages we send (less with flattening)
GRAPPA_DECLARE_STAT(SimpleStatistic<uint64_t>, gce_completions_sent);

namespace Grappa {
/// @addtogroup Synchronization
/// @{

/// GlobalCompletionEvent (GCE):
/// Synchronization construct for determining when a global phase of asynchronous tasks have
/// all completed. For example, can be used to ensure that all tasks of a parallel loop have
/// completed, including tasks or asynchronous delegates spawned during execution of the
/// parallel loop.
///
/// A GlobalCompletionEvent must be replicated at the same address on all cores (the easiest
/// way is to declare it as file-global or static storage). TODO: allow dynamic allocation
/// in Grappa linear address space.
///
/// Anyone calling "wait" after at least some work has been "enrolled" globally will block.
/// When *all* work has been completed on all cores, all tasks waiting on the GCE will be woken.
///
/// To ensure consistent behavior and guarantee deadlock freedom, every "enroll" must be
/// causally followed by "complete", so either must be completed from the same task that
/// called "enroll" or from a task spawned (transitively) from the enrolling task.
///
/// This is meant to be a reusable barrier; GCE's should begin in a state where a call to
/// `wait` will fall through, and end up, after all tasks are completed, back in the same
/// state. Note: `reset` no longer needs to be called between phases. Instead, it just
/// must be guaranteed that at least one task has been enrolled before anyone tries to
/// call `wait` otherwise they may fall through before the enrollment has completed.
class GlobalCompletionEvent : public CompletionEvent {
  // All nodes
  // (count)
  // (cv)
  bool event_in_progress;
  Core master_core;

  // Master barrier only
  Core cores_out;

  /// pointer to shared arg for loops that use a GCE
  const void * shared_ptr;

  struct DoComplete {
    GlobalCompletionEvent * gce;
    int64_t dec;

    DoComplete(): gce(nullptr), dec(0) {}

    void operator()() {
      gce->complete(dec);
    }
  };

  class CompletionMessage: public Message<DoComplete> {
  public:
    Core target;
    int64_t completes_to_send;
    CompletionMessage(Core target = -1): Message(), completes_to_send(0), target(target) {}

    bool waiting_to_send() {
      return this->is_enqueued_ && !this->is_sent_;
    }

    virtual void mark_sent() {
      Core dest = this->destination_;
      DVLOG(5) << "marking sent " << PRINT_MSG(*this);
      Message<DoComplete>::mark_sent();

      if (Grappa::mycore() == this->source_) {
        this->reset();
        if (completes_to_send > 0) {
          DVLOG(5) << "re-sending -- " << completes_to_send << " to Core[" << dest << "] " << PRINT_MSG(*this);
          (*this)->dec = completes_to_send;
          completes_to_send = 0;
          this->enqueue(target);
        }
      }
    }

    virtual const size_t size() const { return sizeof(*this); }
  };

  CompletionMessage * completion_msgs;

  CompletionMessage& get_completion_msg(Core c) {
    if (completion_msgs == nullptr) { init_completion_msgs(); }
    return completion_msgs[c];
  }

  inline void init_completion_msgs() {
    // completion_msgs = new CompletionMessage[cores()];
    completion_msgs = reinterpret_cast<CompletionMessage*>(
      impl::locale_shared_memory.allocate_aligned(sizeof(CompletionMessage)*cores(), 8)
    );

    for (Core c=0; c<cores(); c++) {
      new (completion_msgs+c) CompletionMessage(c); // call constructor!
      completion_msgs[c]->gce = this; // (pointer must be the same on all cores)
    }
  }

public:

  /// Send a completion message to the originating core. Uses the local instance of the gce to
  /// keep track of information in order to flatten completions automatically.
  void send_completion(Core owner, int64_t dec = 1) {
    if (owner == mycore()) {
      VLOG(5) << "complete locally ";
      this->complete(dec);
    } else {
      gce_total_remote_completions++;
      auto& cm = get_completion_msg(owner);
      if (cm.waiting_to_send()) {
        cm.completes_to_send++;
        DVLOG(5) << "flattening completion to Core[" << owner << "] (currently at " << cm.completes_to_send << ")";
      } else {
        CHECK_EQ(cm.completes_to_send, 0) << "why haven't we sent these already? cm(" << &cm << ", is_sent: " << cm.is_sent_ << ", is_enqueued: " << cm.is_enqueued_ << ", dest: " << cm.destination_ << ")";
        DVLOG(5) << "sending " << dec << " to Core[" << owner << "]";
        cm->dec = dec;
        gce_completions_sent++;
        cm.enqueue(owner);
      }
    }
  }

  GlobalCompletionEvent(): master_core(0), completion_msgs(nullptr) {
    reset();
  }
  ~GlobalCompletionEvent() {
    if (completion_msgs != nullptr) impl::locale_shared_memory.deallocate(completion_msgs);
  }

  inline void set_shared_ptr(const void* p) { shared_ptr = p; }
  template<typename T> inline const T* get_shared_ptr() { return reinterpret_cast<const T*>(shared_ptr); }

  /// This is the state the GCE's on each core should be in at the beginning, and the
  /// state they should end up in after a Completion phase. It should no longer be necessary
  /// to call `reset` between calls to `wait` as long as nothing fishy is going on.
  void reset() {
    count = 0;
    cv.waiters_ = 0;
    cores_out = 0;
    event_in_progress = false;
  }

  /// Enroll more things that need to be completed before the global completion is, well, complete.
  /// This will send a cancel to the master if this core previously entered the cancellable barrier.
  ///
  /// Blocks until cancel completes (if it must cancel) to ensure correct ordering, therefore
  /// cannot be called from message handler.
  void enroll(int64_t inc = 1) {
    if (inc == 0) return;

    CHECK_GE(inc, 1);
    count += inc;
    DVLOG(5) << "enroll " << inc << " -> " << count << " gce("<<this<<")";

    // first one to have work here
    if (count == inc) { // count[0 -> inc]
      event_in_progress = true; // optimization to save checking in wait()
      // cancel barrier
      Core co = delegate::call(master_core, [this] {
        cores_out++;
        return cores_out;
      });
      // first one to cancel barrier should make sure other cores are ready to wait
      if (co == 1) { // cores_out[0 -> 1]
        event_in_progress = true;
        call_on_all_cores([this] {
          event_in_progress = true;
        });
        CHECK(event_in_progress);
      }
      // block until cancelled
      CHECK_GT(count, 0);
      DVLOG(2) << "cores_out: " << co << ", count: " << count;
    }
  }

  /// Mark a certain number of things completed. When the global count on all cores goes to 0, all
  /// tasks waiting on the GCE will be woken.
  ///
  /// Note: this can be called in a message handler (e.g. remote completes from stolen tasks).
  void complete(int64_t dec = 1) {
    count -= dec;
    DVLOG(4) << "complete (" << count << ") -- gce(" << this << ")";

    // out of work here
    if (count == 0) { // count[dec -> 0]
      // enter cancellable barrier
      send_heap_message(master_core, [this] {
        cores_out--;
        DVLOG(4) << "core entered barrier (cores_out:"<< cores_out <<")";

        // if all are in
        if (cores_out == 0) { // cores_out[1 -> 0]
          CHECK_EQ(count, 0);
          // notify everyone to wake
          for (Core c = 0; c < cores(); c++) {
            send_heap_message(c, [this] {
              CHECK_EQ(count, 0);
              DVLOG(3) << "broadcast";
              broadcast(&cv); // wake anyone who was waiting here
              reset(); // reset, now anyone else calling `wait` should fall through
            });
          }
        }
      });
    }
  }

  /// Suspend calling task until all tasks completed (including additional tasks enrolled
  /// before count goes to 0). This can be called from as many tasks as desired on
  /// different cores, as long as it is ensured that a task in the desired phase has been
  /// enrolled before wait is called.
  ///
  /// If no tasks have been enrolled, or all have been completed by the time `wait` is called,
  /// this will fall through and not suspend the calling task.
  void wait() {
    DVLOG(3) << "wait(): gce(" << this << " event_in_progress: " << event_in_progress << ", count: " << count << ")";
    if (event_in_progress) {
      Grappa::wait(&cv);
    } else {
      // conservative check, in case we're calling `wait` without calling `enroll`
      if (delegate::call(master_core, [this]{ return cores_out; }) > 0) {
//      if (delegate::call(master_core, [this]{ return event_in_progress; })) {
        Grappa::wait(&cv);
        DVLOG(3) << "woke from conservative check";
      }
      DVLOG(3) << "fell thru conservative check";
    }
    CHECK(!event_in_progress) << " gce(" << this << ", count:" << count << ")";
    CHECK_EQ(count, 0);
  }

};

/// Allow calling send_completion using the old way (with global address)
/// TODO: replace all instances with gce.send_completion and remove this?
inline void complete(GlobalAddress<GlobalCompletionEvent> ce, int64_t decr = 1) {
  DVLOG(5) << "called remote complete";
  if (FLAGS_flatten_completions) {
    ce.pointer()->send_completion(ce.core(), decr);
  } else {
    if (ce.node() == mycore()) {
      ce.pointer()->complete(decr);
    } else {
      if (decr == 1) {
        // (common case) don't send full 8 bytes just to decrement by 1
        send_heap_message(ce.node(), [ce] {
          ce.pointer()->complete();
        });
      } else {
        send_heap_message(ce.node(), [ce,decr] {
          ce.pointer()->complete(decr);
        });
      }
    }
  }
}
/// @}
} // namespace Grappa

/// Synchronizing spawns
namespace Grappa {
  /// @addtogroup Tasking
  /// @{

  /// Synchronizing private task spawn. Automatically enrolls task with GlobalCompletionEvent and
  /// does local `complete` when done (if GCE is non-null).
  template<typename TF>
  void privateTask(GlobalCompletionEvent * gce, TF tf) {
    gce->enroll();
    privateTask([gce,tf] {
      tf();
      gce->complete();
    });
  }

  /// Synchronizing private task spawn. Automatically enrolls task with GlobalCompletionEvent and
  /// does local `complete` when done (if GCE is non-null).
  /// In this version, GCE is a template parameter to avoid taking up space in the task's args.
  template<GlobalCompletionEvent * GCE, typename TF>
  void privateTask(TF tf) {
    if (GCE) GCE->enroll();
    Core origin = mycore();
    privateTask([tf] {
      tf();
      if (GCE) GCE->complete();
    });
  }

  /// Synchronizing public task spawn. Automatically enrolls task with GlobalCompletionEvent and
  /// sends `complete`  message when done (if GCE is non-null).
  template<GlobalCompletionEvent * GCE, typename TF>
  inline void publicTask(TF tf) {
    if (GCE) GCE->enroll();
    Core origin = mycore();
    publicTask([origin,tf] {
      DVLOG(5) << "in public task";
      tf();
      if (GCE) complete(make_global(GCE,origin));
    });
  }

  ///@}
} // namespace Grappa
<commit_msg>GCE: use locale_{alloc,free}<commit_after>#pragma once

#include "Communicator.hpp"
#include "CompletionEvent.hpp"
#include "Tasking.hpp"
#include "Message.hpp"
#include "MessagePool.hpp"
#include "Delegate.hpp"
#include "Collective.hpp"
#include "Timestamp.hpp"
#include <type_traits>
#include "Statistics.hpp"

#define PRINT_MSG(m) "msg(" << &(m) << ", src:" << (m).source_ << ", dst:" << (m).destination_ << ", enq:" << (m).is_enqueued_ << ", sent:" << (m).is_sent_ << ", deliv:" << (m).is_delivered_ << ")"

DECLARE_bool( flatten_completions );

/// total number of times "complete" has to be called on another core
GRAPPA_DECLARE_STAT(SimpleStatistic<uint64_t>, gce_total_remote_completions);

/// actual number of completion messages we send (less with flattening)
GRAPPA_DECLARE_STAT(SimpleStatistic<uint64_t>, gce_completions_sent);

namespace Grappa {
/// @addtogroup Synchronization
/// @{

/// GlobalCompletionEvent (GCE):
/// Synchronization construct for determining when a global phase of asynchronous tasks have
/// all completed. For example, can be used to ensure that all tasks of a parallel loop have
/// completed, including tasks or asynchronous delegates spawned during execution of the
/// parallel loop.
///
/// A GlobalCompletionEvent must be replicated at the same address on all cores (the easiest
/// way is to declare it as file-global or static storage). TODO: allow dynamic allocation
/// in Grappa linear address space.
///
/// Anyone calling "wait" after at least some work has been "enrolled" globally will block.
/// When *all* work has been completed on all cores, all tasks waiting on the GCE will be woken.
///
/// To ensure consistent behavior and guarantee deadlock freedom, every "enroll" must be
/// causally followed by "complete", so either must be completed from the same task that
/// called "enroll" or from a task spawned (transitively) from the enrolling task.
///
/// This is meant to be a reusable barrier; GCE's should begin in a state where a call to
/// `wait` will fall through, and end up, after all tasks are completed, back in the same
/// state. Note: `reset` no longer needs to be called between phases. Instead, it just
/// must be guaranteed that at least one task has been enrolled before anyone tries to
/// call `wait` otherwise they may fall through before the enrollment has completed.
class GlobalCompletionEvent : public CompletionEvent {
  // All nodes
  // (count)
  // (cv)
  bool event_in_progress;
  Core master_core;

  // Master barrier only
  Core cores_out;

  /// pointer to shared arg for loops that use a GCE
  const void * shared_ptr;

  struct DoComplete {
    GlobalCompletionEvent * gce;
    int64_t dec;

    DoComplete(): gce(nullptr), dec(0) {}

    void operator()() {
      gce->complete(dec);
    }
  };

  class CompletionMessage: public Message<DoComplete> {
  public:
    Core target;
    int64_t completes_to_send;
    CompletionMessage(Core target = -1): Message(), completes_to_send(0), target(target) {}

    bool waiting_to_send() {
      return this->is_enqueued_ && !this->is_sent_;
    }

    virtual void mark_sent() {
      Core dest = this->destination_;
      DVLOG(5) << "marking sent " << PRINT_MSG(*this);
      Message<DoComplete>::mark_sent();

      if (Grappa::mycore() == this->source_) {
        this->reset();
        if (completes_to_send > 0) {
          DVLOG(5) << "re-sending -- " << completes_to_send << " to Core[" << dest << "] " << PRINT_MSG(*this);
          (*this)->dec = completes_to_send;
          completes_to_send = 0;
          this->enqueue(target);
        }
      }
    }

    virtual const size_t size() const { return sizeof(*this); }
  };

  CompletionMessage * completion_msgs;

  CompletionMessage& get_completion_msg(Core c) {
    if (completion_msgs == nullptr) { init_completion_msgs(); }
    return completion_msgs[c];
  }

  inline void init_completion_msgs() {
    completion_msgs = locale_alloc<CompletionMessage>(cores());

    for (Core c=0; c<cores(); c++) {
      new (completion_msgs+c) CompletionMessage(c); // call constructor!
      completion_msgs[c]->gce = this; // (pointer must be the same on all cores)
    }
  }

public:

  /// Send a completion message to the originating core. Uses the local instance of the gce to
  /// keep track of information in order to flatten completions automatically.
  void send_completion(Core owner, int64_t dec = 1) {
    if (owner == mycore()) {
      VLOG(5) << "complete locally ";
      this->complete(dec);
    } else {
      gce_total_remote_completions++;
      auto& cm = get_completion_msg(owner);
      if (cm.waiting_to_send()) {
        cm.completes_to_send++;
        DVLOG(5) << "flattening completion to Core[" << owner << "] (currently at " << cm.completes_to_send << ")";
      } else {
        CHECK_EQ(cm.completes_to_send, 0) << "why haven't we sent these already? cm(" << &cm << ", is_sent: " << cm.is_sent_ << ", is_enqueued: " << cm.is_enqueued_ << ", dest: " << cm.destination_ << ")";
        DVLOG(5) << "sending " << dec << " to Core[" << owner << "]";
        cm->dec = dec;
        gce_completions_sent++;
        cm.enqueue(owner);
      }
    }
  }

  GlobalCompletionEvent(): master_core(0), completion_msgs(nullptr) {
    reset();
  }
  ~GlobalCompletionEvent() {
    if (completion_msgs != nullptr) locale_free(completion_msgs);
  }

  inline void set_shared_ptr(const void* p) { shared_ptr = p; }
  template<typename T> inline const T* get_shared_ptr() { return reinterpret_cast<const T*>(shared_ptr); }

  /// This is the state the GCE's on each core should be in at the beginning, and the
  /// state they should end up in after a Completion phase. It should no longer be necessary
  /// to call `reset` between calls to `wait` as long as nothing fishy is going on.
  void reset() {
    count = 0;
    cv.waiters_ = 0;
    cores_out = 0;
    event_in_progress = false;
  }

  /// Enroll more things that need to be completed before the global completion is, well, complete.
  /// This will send a cancel to the master if this core previously entered the cancellable barrier.
  ///
  /// Blocks until cancel completes (if it must cancel) to ensure correct ordering, therefore
  /// cannot be called from message handler.
  void enroll(int64_t inc = 1) {
    if (inc == 0) return;

    CHECK_GE(inc, 1);
    count += inc;
    DVLOG(5) << "enroll " << inc << " -> " << count << " gce("<<this<<")";

    // first one to have work here
    if (count == inc) { // count[0 -> inc]
      event_in_progress = true; // optimization to save checking in wait()
      // cancel barrier
      Core co = delegate::call(master_core, [this] {
        cores_out++;
        return cores_out;
      });
      // first one to cancel barrier should make sure other cores are ready to wait
      if (co == 1) { // cores_out[0 -> 1]
        event_in_progress = true;
        call_on_all_cores([this] {
          event_in_progress = true;
        });
        CHECK(event_in_progress);
      }
      // block until cancelled
      CHECK_GT(count, 0);
      DVLOG(2) << "cores_out: " << co << ", count: " << count;
    }
  }

  /// Mark a certain number of things completed. When the global count on all cores goes to 0, all
  /// tasks waiting on the GCE will be woken.
  ///
  /// Note: this can be called in a message handler (e.g. remote completes from stolen tasks).
  void complete(int64_t dec = 1) {
    count -= dec;
    DVLOG(4) << "complete (" << count << ") -- gce(" << this << ")";

    // out of work here
    if (count == 0) { // count[dec -> 0]
      // enter cancellable barrier
      send_heap_message(master_core, [this] {
        cores_out--;
        DVLOG(4) << "core entered barrier (cores_out:"<< cores_out <<")";

        // if all are in
        if (cores_out == 0) { // cores_out[1 -> 0]
          CHECK_EQ(count, 0);
          // notify everyone to wake
          for (Core c = 0; c < cores(); c++) {
            send_heap_message(c, [this] {
              CHECK_EQ(count, 0);
              DVLOG(3) << "broadcast";
              broadcast(&cv); // wake anyone who was waiting here
              reset(); // reset, now anyone else calling `wait` should fall through
            });
          }
        }
      });
    }
  }

  /// Suspend calling task until all tasks completed (including additional tasks enrolled
  /// before count goes to 0). This can be called from as many tasks as desired on
  /// different cores, as long as it is ensured that a task in the desired phase has been
  /// enrolled before wait is called.
  ///
  /// If no tasks have been enrolled, or all have been completed by the time `wait` is called,
  /// this will fall through and not suspend the calling task.
  void wait() {
    DVLOG(3) << "wait(): gce(" << this << " event_in_progress: " << event_in_progress << ", count: " << count << ")";
    if (event_in_progress) {
      Grappa::wait(&cv);
    } else {
      // conservative check, in case we're calling `wait` without calling `enroll`
      if (delegate::call(master_core, [this]{ return cores_out; }) > 0) {
//      if (delegate::call(master_core, [this]{ return event_in_progress; })) {
        Grappa::wait(&cv);
        DVLOG(3) << "woke from conservative check";
      }
      DVLOG(3) << "fell thru conservative check";
    }
    CHECK(!event_in_progress) << " gce(" << this << ", count:" << count << ")";
    CHECK_EQ(count, 0);
  }

};

/// Allow calling send_completion using the old way (with global address)
/// TODO: replace all instances with gce.send_completion and remove this?
inline void complete(GlobalAddress<GlobalCompletionEvent> ce, int64_t decr = 1) {
  DVLOG(5) << "called remote complete";
  if (FLAGS_flatten_completions) {
    ce.pointer()->send_completion(ce.core(), decr);
  } else {
    if (ce.node() == mycore()) {
      ce.pointer()->complete(decr);
    } else {
      if (decr == 1) {
        // (common case) don't send full 8 bytes just to decrement by 1
        send_heap_message(ce.node(), [ce] {
          ce.pointer()->complete();
        });
      } else {
        send_heap_message(ce.node(), [ce,decr] {
          ce.pointer()->complete(decr);
        });
      }
    }
  }
}
/// @}
} // namespace Grappa

/// Synchronizing spawns
namespace Grappa {
  /// @addtogroup Tasking
  /// @{

  /// Synchronizing private task spawn. Automatically enrolls task with GlobalCompletionEvent and
  /// does local `complete` when done (if GCE is non-null).
  template<typename TF>
  void privateTask(GlobalCompletionEvent * gce, TF tf) {
    gce->enroll();
    privateTask([gce,tf] {
      tf();
      gce->complete();
    });
  }

  /// Synchronizing private task spawn. Automatically enrolls task with GlobalCompletionEvent and
  /// does local `complete` when done (if GCE is non-null).
  /// In this version, GCE is a template parameter to avoid taking up space in the task's args.
  template<GlobalCompletionEvent * GCE, typename TF>
  void privateTask(TF tf) {
    if (GCE) GCE->enroll();
    Core origin = mycore();
    privateTask([tf] {
      tf();
      if (GCE) GCE->complete();
    });
  }

  /// Synchronizing public task spawn. Automatically enrolls task with GlobalCompletionEvent and
  /// sends `complete`  message when done (if GCE is non-null).
  template<GlobalCompletionEvent * GCE, typename TF>
  inline void publicTask(TF tf) {
    if (GCE) GCE->enroll();
    Core origin = mycore();
    publicTask([origin,tf] {
      DVLOG(5) << "in public task";
      tf();
      if (GCE) complete(make_global(GCE,origin));
    });
  }

  ///@}
} // namespace Grappa
<|endoftext|>


<commit_before>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2011 Sergey Lisitsyn
 * Copyright (C) 2011 Berlin Institute of Technology and Max-Planck-Society
 */

#include <shogun/preprocessor/KernelLocalTangentSpaceAlignment.h>
#ifdef HAVE_LAPACK
#include <shogun/mathematics/lapack.h>
#include <shogun/mathematics/arpack.h>
#include <shogun/lib/Time.h>
#include <shogun/lib/common.h>
#include <shogun/mathematics/Math.h>
#include <shogun/io/SGIO.h>
#include <shogun/distance/Distance.h>
#include <shogun/lib/Signal.h>
#include <shogun/base/Parallel.h>

#ifdef HAVE_PTHREAD
#include <pthread.h>
#endif

using namespace shogun;

#ifndef DOXYGEN_SHOULD_SKIP_THIS
struct KLTSA_THREAD_PARAM
{
	/// starting index of loop
	int32_t idx_start;
	/// step of loop
	int32_t idx_step;
	/// stop index of loop
	int32_t idx_stop;
	/// number of neighbors
	int32_t m_k;
	/// target dimension
	int32_t target_dim;
	/// number of objects
	int32_t N;
	/// matrix containing indexes of ith vector's neighbors in ith column
	const int32_t* neighborhood_matrix;
	/// kernel matrix
	const float64_t* kernel_matrix;
	/// local gram matrix
	float64_t* local_gram_matrix;
	/// eigenvalues
	float64_t* ev_vector;
	/// G matrix
	float64_t* G_matrix;
	/// weight matrix
	float64_t* W_matrix;
#ifdef HAVE_PTHREAD
	/// lock used on modifying to weight matrix
	PTHREAD_LOCK_T* W_matrix_lock;
#endif
};
#endif

CKernelLocalTangentSpaceAlignment::CKernelLocalTangentSpaceAlignment() :
		CKernelLocallyLinearEmbedding()
{
}

CKernelLocalTangentSpaceAlignment::~CKernelLocalTangentSpaceAlignment()
{
}

bool CKernelLocalTangentSpaceAlignment::init(CFeatures* features)
{
	return true;
}

void CKernelLocalTangentSpaceAlignment::cleanup()
{
}

const char* CKernelLocalTangentSpaceAlignment::get_name() const
{
	return "KernelLocalTangentSpaceAlignment";
};

EPreprocessorType CKernelLocalTangentSpaceAlignment::get_type() const
{
	return P_KERNELLOCALTANGENTSPACEALIGNMENT;
};

SGMatrix<float64_t> CKernelLocalTangentSpaceAlignment::construct_weight_matrix(SGMatrix<float64_t> kernel_matrix,
                                                                               SGMatrix<int32_t> neighborhood_matrix,
                                                                               int32_t target_dim)
{
	int32_t N = kernel_matrix.num_cols;
	int32_t t;
#ifdef HAVE_PTHREAD
	int32_t num_threads = parallel->get_num_threads();
	ASSERT(num_threads>0);
	// allocate threads and params
	pthread_t* threads = SG_MALLOC(pthread_t, num_threads);
	KLTSA_THREAD_PARAM* parameters = SG_MALLOC(KLTSA_THREAD_PARAM, num_threads);
#else
	int32_t num_threads = 1;
#endif

	// init matrices and norm factor to be used
	float64_t* local_gram_matrix = SG_MALLOC(float64_t, m_k*m_k*num_threads);
	float64_t* G_matrix = SG_MALLOC(float64_t, m_k*(1+target_dim)*num_threads);
	float64_t* W_matrix = SG_CALLOC(float64_t, N*N);
	float64_t* ev_vector = SG_MALLOC(float64_t, m_k*num_threads);

#ifdef HAVE_PTHREAD
	PTHREAD_LOCK_T W_matrix_lock;
	pthread_attr_t attr;
	PTHREAD_LOCK_INIT(&W_matrix_lock);
	pthread_attr_init(&attr);
	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

	for (t=0; t<num_threads; t++)
	{
		KLTSA_THREAD_PARAM params = {t,num_threads,N,m_k,target_dim,N,neighborhood_matrix.matrix,
		                            kernel_matrix.matrix,local_gram_matrix+(m_k*m_k)*t,ev_vector+m_k*t,
		                            G_matrix+(m_k*(1+target_dim))*t,W_matrix,&W_matrix_lock};
		parameters[t] = params;
		pthread_create(&threads[t], &attr, run_kltsa_thread, (void*)&parameters[t]);
	}
	for (t=0; t<num_threads; t++)
		pthread_join(threads[t], NULL);
	PTHREAD_LOCK_DESTROY(&W_matrix_lock);
	SG_FREE(parameters);
	SG_FREE(threads);
#else
	KLTSA_THREAD_PARAM single_thread_param = {0,1,N,m_k,target_dim,neighborhood_matrix.matrix,
	                                          kernel_matrix.matrix,local_gram_matrix,ev_vector,
	                                          G_matrix,W_matrix};
	run_kltsa_thread((void*)&single_thread_param);
#endif

	// clean
	SG_FREE(local_gram_matrix);
	SG_FREE(ev_vector);
	SG_FREE(G_matrix);

	for (int32_t i=0; i<N; i++)
	{
		for (int32_t j=0; j<m_k; j++)
			W_matrix[N*neighborhood_matrix[j*N+i]+neighborhood_matrix[j*N+i]] += 1.0;
	}

	return SGMatrix<float64_t>(W_matrix,N,N);
}

void* CKernelLocalTangentSpaceAlignment::run_kltsa_thread(void* p)
{
	KLTSA_THREAD_PARAM* parameters = (KLTSA_THREAD_PARAM*)p;
	int32_t idx_start = parameters->idx_start;
	int32_t idx_step = parameters->idx_step;
	int32_t idx_stop = parameters->idx_stop;
	int32_t m_k = parameters->m_k;
	int32_t target_dim = parameters->target_dim;
	int32_t N = parameters->N;
	const int32_t* neighborhood_matrix = parameters->neighborhood_matrix;
	const float64_t* kernel_matrix = parameters->kernel_matrix;
	float64_t* ev_vector = parameters->ev_vector;
	float64_t* G_matrix = parameters->G_matrix;
	float64_t* local_gram_matrix = parameters->local_gram_matrix;
	float64_t* W_matrix = parameters->W_matrix;
#ifdef HAVE_PTHREAD
	PTHREAD_LOCK_T* W_matrix_lock = parameters->W_matrix_lock;
#endif

	int32_t i,j,k;

	for (i=idx_start; i<idx_stop; i+=idx_step)
	{
		for (j=0; j<m_k; j++)
			G_matrix[j] = 1.0/CMath::sqrt((float64_t)m_k);

		for (j=0; j<m_k; j++)
		{
			for (k=0; k<m_k; k++)
				local_gram_matrix[j*m_k+k] = kernel_matrix[neighborhood_matrix[j*N+i]*N+neighborhood_matrix[k*N+i]];
		}

		CMath::center_matrix(local_gram_matrix,m_k,m_k);

		int32_t info = 0;
		wrap_dsyevr('V','U',m_k,local_gram_matrix,m_k,m_k-target_dim+1,m_k,ev_vector,G_matrix+m_k,&info);
		ASSERT(info==0);

		for (j=0; j<target_dim/2; j++)
		{
			cblas_dswap(m_k,G_matrix+(j+1)*m_k,1,G_matrix+(target_dim-j)*m_k,1);
		}

		cblas_dgemm(CblasColMajor,CblasNoTrans,CblasTrans,
		            m_k,m_k,1+target_dim,
		            1.0,G_matrix,m_k,
		                G_matrix,m_k,
		            0.0,local_gram_matrix,m_k);

#ifdef HAVE_PTHREAD
		PTHREAD_LOCK(W_matrix_lock);
#endif
		for (j=0; j<m_k; j++)
		{
			for (k=0; k<m_k; k++)
				W_matrix[N*neighborhood_matrix[k*N+i]+neighborhood_matrix[j*N+i]] -= local_gram_matrix[j*m_k+k];
		}
#ifdef HAVE_PTHREAD
		PTHREAD_UNLOCK(W_matrix_lock);
#endif
	}
	return NULL;
}

#endif /* HAVE_LAPACK */
<commit_msg>Fixed memory leak at KLTSA<commit_after>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2011 Sergey Lisitsyn
 * Copyright (C) 2011 Berlin Institute of Technology and Max-Planck-Society
 */

#include <shogun/preprocessor/KernelLocalTangentSpaceAlignment.h>
#ifdef HAVE_LAPACK
#include <shogun/mathematics/lapack.h>
#include <shogun/mathematics/arpack.h>
#include <shogun/lib/Time.h>
#include <shogun/lib/common.h>
#include <shogun/mathematics/Math.h>
#include <shogun/io/SGIO.h>
#include <shogun/distance/Distance.h>
#include <shogun/lib/Signal.h>
#include <shogun/base/Parallel.h>

#ifdef HAVE_PTHREAD
#include <pthread.h>
#endif

using namespace shogun;

#ifndef DOXYGEN_SHOULD_SKIP_THIS
struct KLTSA_THREAD_PARAM
{
	/// starting index of loop
	int32_t idx_start;
	/// step of loop
	int32_t idx_step;
	/// stop index of loop
	int32_t idx_stop;
	/// number of neighbors
	int32_t m_k;
	/// target dimension
	int32_t target_dim;
	/// number of objects
	int32_t N;
	/// matrix containing indexes of ith vector's neighbors in ith column
	const int32_t* neighborhood_matrix;
	/// kernel matrix
	const float64_t* kernel_matrix;
	/// local gram matrix
	float64_t* local_gram_matrix;
	/// eigenvalues
	float64_t* ev_vector;
	/// G matrix
	float64_t* G_matrix;
	/// weight matrix
	float64_t* W_matrix;
#ifdef HAVE_PTHREAD
	/// lock used on modifying to weight matrix
	PTHREAD_LOCK_T* W_matrix_lock;
#endif
};
#endif

CKernelLocalTangentSpaceAlignment::CKernelLocalTangentSpaceAlignment() :
		CKernelLocallyLinearEmbedding()
{
}

CKernelLocalTangentSpaceAlignment::~CKernelLocalTangentSpaceAlignment()
{
}

bool CKernelLocalTangentSpaceAlignment::init(CFeatures* features)
{
	return true;
}

void CKernelLocalTangentSpaceAlignment::cleanup()
{
}

const char* CKernelLocalTangentSpaceAlignment::get_name() const
{
	return "KernelLocalTangentSpaceAlignment";
};

EPreprocessorType CKernelLocalTangentSpaceAlignment::get_type() const
{
	return P_KERNELLOCALTANGENTSPACEALIGNMENT;
};

SGMatrix<float64_t> CKernelLocalTangentSpaceAlignment::construct_weight_matrix(SGMatrix<float64_t> kernel_matrix,
                                                                               SGMatrix<int32_t> neighborhood_matrix,
                                                                               int32_t target_dim)
{
	int32_t N = kernel_matrix.num_cols;
	int32_t t;
#ifdef HAVE_PTHREAD
	int32_t num_threads = parallel->get_num_threads();
	ASSERT(num_threads>0);
	// allocate threads and params
	pthread_t* threads = SG_MALLOC(pthread_t, num_threads);
	KLTSA_THREAD_PARAM* parameters = SG_MALLOC(KLTSA_THREAD_PARAM, num_threads);
#else
	int32_t num_threads = 1;
#endif

	// init matrices and norm factor to be used
	float64_t* local_gram_matrix = SG_MALLOC(float64_t, m_k*m_k*num_threads);
	float64_t* G_matrix = SG_MALLOC(float64_t, m_k*(1+target_dim)*num_threads);
	float64_t* W_matrix = SG_CALLOC(float64_t, N*N);
	float64_t* ev_vector = SG_MALLOC(float64_t, m_k*num_threads);

#ifdef HAVE_PTHREAD
	PTHREAD_LOCK_T W_matrix_lock;
	pthread_attr_t attr;
	PTHREAD_LOCK_INIT(&W_matrix_lock);
	pthread_attr_init(&attr);
	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

	for (t=0; t<num_threads; t++)
	{
		KLTSA_THREAD_PARAM params = {t,num_threads,N,m_k,target_dim,N,neighborhood_matrix.matrix,
		                            kernel_matrix.matrix,local_gram_matrix+(m_k*m_k)*t,ev_vector+m_k*t,
		                            G_matrix+(m_k*(1+target_dim))*t,W_matrix,&W_matrix_lock};
		parameters[t] = params;
		pthread_create(&threads[t], &attr, run_kltsa_thread, (void*)&parameters[t]);
	}
	for (t=0; t<num_threads; t++)
		pthread_join(threads[t], NULL);
	PTHREAD_LOCK_DESTROY(&W_matrix_lock);
	SG_FREE(parameters);
	SG_FREE(threads);
#else
	KLTSA_THREAD_PARAM single_thread_param = {0,1,N,m_k,target_dim,neighborhood_matrix.matrix,
	                                          kernel_matrix.matrix,local_gram_matrix,ev_vector,
	                                          G_matrix,W_matrix};
	run_kltsa_thread((void*)&single_thread_param);
#endif

	// clean
	SG_FREE(local_gram_matrix);
	SG_FREE(ev_vector);
	SG_FREE(G_matrix);
	kernel_matrix.destroy_matrix();

	for (int32_t i=0; i<N; i++)
	{
		for (int32_t j=0; j<m_k; j++)
			W_matrix[N*neighborhood_matrix[j*N+i]+neighborhood_matrix[j*N+i]] += 1.0;
	}

	return SGMatrix<float64_t>(W_matrix,N,N);
}

void* CKernelLocalTangentSpaceAlignment::run_kltsa_thread(void* p)
{
	KLTSA_THREAD_PARAM* parameters = (KLTSA_THREAD_PARAM*)p;
	int32_t idx_start = parameters->idx_start;
	int32_t idx_step = parameters->idx_step;
	int32_t idx_stop = parameters->idx_stop;
	int32_t m_k = parameters->m_k;
	int32_t target_dim = parameters->target_dim;
	int32_t N = parameters->N;
	const int32_t* neighborhood_matrix = parameters->neighborhood_matrix;
	const float64_t* kernel_matrix = parameters->kernel_matrix;
	float64_t* ev_vector = parameters->ev_vector;
	float64_t* G_matrix = parameters->G_matrix;
	float64_t* local_gram_matrix = parameters->local_gram_matrix;
	float64_t* W_matrix = parameters->W_matrix;
#ifdef HAVE_PTHREAD
	PTHREAD_LOCK_T* W_matrix_lock = parameters->W_matrix_lock;
#endif

	int32_t i,j,k;

	for (i=idx_start; i<idx_stop; i+=idx_step)
	{
		for (j=0; j<m_k; j++)
			G_matrix[j] = 1.0/CMath::sqrt((float64_t)m_k);

		for (j=0; j<m_k; j++)
		{
			for (k=0; k<m_k; k++)
				local_gram_matrix[j*m_k+k] = kernel_matrix[neighborhood_matrix[j*N+i]*N+neighborhood_matrix[k*N+i]];
		}

		CMath::center_matrix(local_gram_matrix,m_k,m_k);

		int32_t info = 0;
		wrap_dsyevr('V','U',m_k,local_gram_matrix,m_k,m_k-target_dim+1,m_k,ev_vector,G_matrix+m_k,&info);
		ASSERT(info==0);

		for (j=0; j<target_dim/2; j++)
		{
			cblas_dswap(m_k,G_matrix+(j+1)*m_k,1,G_matrix+(target_dim-j)*m_k,1);
		}

		cblas_dgemm(CblasColMajor,CblasNoTrans,CblasTrans,
		            m_k,m_k,1+target_dim,
		            1.0,G_matrix,m_k,
		                G_matrix,m_k,
		            0.0,local_gram_matrix,m_k);

#ifdef HAVE_PTHREAD
		PTHREAD_LOCK(W_matrix_lock);
#endif
		for (j=0; j<m_k; j++)
		{
			for (k=0; k<m_k; k++)
				W_matrix[N*neighborhood_matrix[k*N+i]+neighborhood_matrix[j*N+i]] -= local_gram_matrix[j*m_k+k];
		}
#ifdef HAVE_PTHREAD
		PTHREAD_UNLOCK(W_matrix_lock);
#endif
	}
	return NULL;
}

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


<commit_before>//! @file ReactorNet.cpp
#include "cantera/zeroD/ReactorNet.h"
#include "cantera/numerics/Integrator.h"
#include "cantera/zeroD/FlowDevice.h"
#include "cantera/zeroD/Wall.h"

#include <cstdio>

using namespace std;

namespace Cantera
{

ReactorNet::ReactorNet() : Cantera::FuncEval(),
    m_integ(0), m_time(0.0), m_init(false),
    m_nv(0), m_rtol(1.0e-9), m_rtolsens(1.0e-4),
    m_atols(1.0e-15), m_atolsens(1.0e-4),
    m_maxstep(-1.0), m_maxErrTestFails(0),
    m_verbose(false), m_ntotpar(0)
{
#ifdef DEBUG_MODE
    m_verbose = true;
#endif
    m_integ = newIntegrator("CVODE");

    // use backward differencing, with a full Jacobian computed
    // numerically, and use a Newton linear iterator

    m_integ->setMethod(BDF_Method);
    m_integ->setProblemType(DENSE + NOJAC);
    m_integ->setIterator(Newton_Iter);
}

ReactorNet::~ReactorNet()
{
    for (size_t n = 0; n < m_reactors.size(); n++) {
        if (m_iown[n]) {
            delete m_reactors[n];
        }
        m_reactors[n] = 0;
    }
    delete m_integ;
}

void ReactorNet::initialize()
{
    size_t n, nv;
    char buf[100];
    m_nv = 0;
    writelog("Initializing reactor network.\n", m_verbose);
    if (m_reactors.empty())
        throw CanteraError("ReactorNet::initialize",
                           "no reactors in network!");
    size_t sensParamNumber = 0;
    m_start.assign(1, 0);
    for (n = 0; n < m_reactors.size(); n++) {
        Reactor& r = *m_reactors[n];
        r.initialize(m_time);
        nv = r.neq();
        m_nparams.push_back(r.nSensParams());
        std::vector<std::pair<void*, int> > sens_objs = r.getSensitivityOrder();
        for (size_t i = 0; i < sens_objs.size(); i++) {
            std::map<size_t, size_t>& s = m_sensOrder[sens_objs[i]];
            for (std::map<size_t, size_t>::iterator iter = s.begin();
                    iter != s.end();
                    ++iter) {
                m_sensIndex.resize(std::max(iter->second + 1, m_sensIndex.size()));
                m_sensIndex[iter->second] = sensParamNumber++;
            }
        }
        m_nv += nv;
        m_start.push_back(m_nv);

        if (m_verbose) {
            sprintf(buf,"Reactor %s: %s variables.\n",
                    int2str(n).c_str(), int2str(nv).c_str());
            writelog(buf);
            sprintf(buf,"            %s sensitivity params.\n",
                    int2str(r.nSensParams()).c_str());
            writelog(buf);
        }
        if (r.type() == FlowReactorType && m_reactors.size() > 1) {
            throw CanteraError("ReactorNet::initialize",
                               "FlowReactors must be used alone.");
        }
    }

    m_connect.resize(m_reactors.size()*m_reactors.size(), 0);
    m_ydot.resize(m_nv,0.0);
    size_t i, j, nin, nout, nw;
    ReactorBase* r, *rj;
    for (i = 0; i < m_reactors.size(); i++) {
        r = m_reactors[i];
        for (j = 0; j < m_reactors.size(); j++) {
            if (i == j) {
                connect(i,j);
            } else {
                rj = m_reactors[j];
                nin = rj->nInlets();
                for (n = 0; n < nin; n++) {
                    if (&rj->inlet(n).out() == r) {
                        connect(i,j);
                    }
                }
                nout = rj->nOutlets();
                for (n = 0; n < nout; n++) {
                    if (&rj->outlet(n).in() == r) {
                        connect(i,j);
                    }
                }
                nw = rj->nWalls();
                for (n = 0; n < nw; n++) {
                    if (&rj->wall(n).left() == rj
                            && &rj->wall(n).right() == r) {
                        connect(i,j);
                    } else if (&rj->wall(n).left() == r
                               && &rj->wall(n).right() == rj) {
                        connect(i,j);
                    }
                }
            }
        }
    }

    m_atol.resize(neq());
    fill(m_atol.begin(), m_atol.end(), m_atols);
    m_integ->setTolerances(m_rtol, neq(), DATA_PTR(m_atol));
    m_integ->setSensitivityTolerances(m_rtolsens, m_atolsens);
    m_integ->setMaxStepSize(m_maxstep);
    m_integ->setMaxErrTestFails(m_maxErrTestFails);
    if (m_verbose) {
        sprintf(buf, "Number of equations: %s\n", int2str(neq()).c_str());
        writelog(buf);
        sprintf(buf, "Maximum time step:   %14.6g\n", m_maxstep);
        writelog(buf);
    }
    m_integ->initialize(m_time, *this);
    m_init = true;
}

void ReactorNet::advance(doublereal time)
{
    if (!m_init) {
        if (m_maxstep < 0.0) {
            m_maxstep = time - m_time;
        }
        initialize();
    }
    m_integ->integrate(time);
    m_time = time;
    updateState(m_integ->solution());
}

double ReactorNet::step(doublereal time)
{
    if (!m_init) {
        if (m_maxstep < 0.0) {
            m_maxstep = time - m_time;
        }
        initialize();
    }
    m_time = m_integ->step(time);
    updateState(m_integ->solution());
    return m_time;
}

void ReactorNet::addReactor(Reactor* r, bool iown)
{
    r->setNetwork(this);
    if (r->type() >= ReactorType) {
        m_reactors.push_back(r);
        m_iown.push_back(iown);
        writelog("Adding reactor "+r->name()+"\n", m_verbose);
    } else {
        writelog("Not adding reactor "+r->name()+
                 ", since type = "+int2str(r->type())+"\n", m_verbose);
    }
}

void ReactorNet::eval(doublereal t, doublereal* y,
                      doublereal* ydot, doublereal* p)
{
    size_t n;
    size_t pstart = 0;

    updateState(y);
    for (n = 0; n < m_reactors.size(); n++) {
        m_reactors[n]->evalEqs(t, y + m_start[n],
                               ydot + m_start[n], p + pstart);
        pstart += m_nparams[n];
    }
}

void ReactorNet::evalJacobian(doublereal t, doublereal* y,
                              doublereal* ydot, doublereal* p, Array2D* j)
{
    doublereal ysave, dy;
    Array2D& jac = *j;

    //evaluate the unperturbed ydot
    eval(t, y, ydot, p);
    for (size_t n = 0; n < m_nv; n++) {

        // perturb x(n)
        ysave = y[n];
        dy = m_atol[n] + fabs(ysave)*m_rtol;
        y[n] = ysave + dy;
        dy = y[n] - ysave;

        // calculate perturbed residual
        eval(t, y, DATA_PTR(m_ydot), p);

        // compute nth column of Jacobian
        for (size_t m = 0; m < m_nv; m++) {
            jac(m,n) = (m_ydot[m] - ydot[m])/dy;
        }
        y[n] = ysave;
    }
}

void ReactorNet::updateState(doublereal* y)
{
    for (size_t n = 0; n < m_reactors.size(); n++) {
        m_reactors[n]->updateState(y + m_start[n]);
    }
}

void ReactorNet::getInitialConditions(doublereal t0,
                                      size_t leny, doublereal* y)
{
    for (size_t n = 0; n < m_reactors.size(); n++) {
        m_reactors[n]->getInitialConditions(t0, m_start[n+1]-m_start[n],
                                            y + m_start[n]);
    }
}

size_t ReactorNet::globalComponentIndex(const string& component, size_t reactor)
{
    if (!m_init) {
        initialize();
    }
    return m_start[reactor] + m_reactors[reactor]->componentIndex(component);
}

void ReactorNet::registerSensitivityReaction(void* reactor,
        size_t reactionIndex, const std::string& name, int leftright)
{
    std::pair<void*, int> R = std::make_pair(reactor, leftright);
    if (m_sensOrder.count(R) &&
            m_sensOrder[R].count(reactionIndex)) {
        throw CanteraError("ReactorNet::registerSensitivityReaction",
                           "Attempted to register duplicate sensitivity reaction");
    }
    m_paramNames.push_back(name);
    m_sensOrder[R][reactionIndex] = m_ntotpar;
    m_ntotpar++;
}

}
<commit_msg>[Reactor] Disable verbose output by default, even in "debug mode"<commit_after>//! @file ReactorNet.cpp
#include "cantera/zeroD/ReactorNet.h"
#include "cantera/numerics/Integrator.h"
#include "cantera/zeroD/FlowDevice.h"
#include "cantera/zeroD/Wall.h"

#include <cstdio>

using namespace std;

namespace Cantera
{

ReactorNet::ReactorNet() : Cantera::FuncEval(),
    m_integ(0), m_time(0.0), m_init(false),
    m_nv(0), m_rtol(1.0e-9), m_rtolsens(1.0e-4),
    m_atols(1.0e-15), m_atolsens(1.0e-4),
    m_maxstep(-1.0), m_maxErrTestFails(0),
    m_verbose(false), m_ntotpar(0)
{
    m_integ = newIntegrator("CVODE");

    // use backward differencing, with a full Jacobian computed
    // numerically, and use a Newton linear iterator

    m_integ->setMethod(BDF_Method);
    m_integ->setProblemType(DENSE + NOJAC);
    m_integ->setIterator(Newton_Iter);
}

ReactorNet::~ReactorNet()
{
    for (size_t n = 0; n < m_reactors.size(); n++) {
        if (m_iown[n]) {
            delete m_reactors[n];
        }
        m_reactors[n] = 0;
    }
    delete m_integ;
}

void ReactorNet::initialize()
{
    size_t n, nv;
    char buf[100];
    m_nv = 0;
    writelog("Initializing reactor network.\n", m_verbose);
    if (m_reactors.empty())
        throw CanteraError("ReactorNet::initialize",
                           "no reactors in network!");
    size_t sensParamNumber = 0;
    m_start.assign(1, 0);
    for (n = 0; n < m_reactors.size(); n++) {
        Reactor& r = *m_reactors[n];
        r.initialize(m_time);
        nv = r.neq();
        m_nparams.push_back(r.nSensParams());
        std::vector<std::pair<void*, int> > sens_objs = r.getSensitivityOrder();
        for (size_t i = 0; i < sens_objs.size(); i++) {
            std::map<size_t, size_t>& s = m_sensOrder[sens_objs[i]];
            for (std::map<size_t, size_t>::iterator iter = s.begin();
                    iter != s.end();
                    ++iter) {
                m_sensIndex.resize(std::max(iter->second + 1, m_sensIndex.size()));
                m_sensIndex[iter->second] = sensParamNumber++;
            }
        }
        m_nv += nv;
        m_start.push_back(m_nv);

        if (m_verbose) {
            sprintf(buf,"Reactor %s: %s variables.\n",
                    int2str(n).c_str(), int2str(nv).c_str());
            writelog(buf);
            sprintf(buf,"            %s sensitivity params.\n",
                    int2str(r.nSensParams()).c_str());
            writelog(buf);
        }
        if (r.type() == FlowReactorType && m_reactors.size() > 1) {
            throw CanteraError("ReactorNet::initialize",
                               "FlowReactors must be used alone.");
        }
    }

    m_connect.resize(m_reactors.size()*m_reactors.size(), 0);
    m_ydot.resize(m_nv,0.0);
    size_t i, j, nin, nout, nw;
    ReactorBase* r, *rj;
    for (i = 0; i < m_reactors.size(); i++) {
        r = m_reactors[i];
        for (j = 0; j < m_reactors.size(); j++) {
            if (i == j) {
                connect(i,j);
            } else {
                rj = m_reactors[j];
                nin = rj->nInlets();
                for (n = 0; n < nin; n++) {
                    if (&rj->inlet(n).out() == r) {
                        connect(i,j);
                    }
                }
                nout = rj->nOutlets();
                for (n = 0; n < nout; n++) {
                    if (&rj->outlet(n).in() == r) {
                        connect(i,j);
                    }
                }
                nw = rj->nWalls();
                for (n = 0; n < nw; n++) {
                    if (&rj->wall(n).left() == rj
                            && &rj->wall(n).right() == r) {
                        connect(i,j);
                    } else if (&rj->wall(n).left() == r
                               && &rj->wall(n).right() == rj) {
                        connect(i,j);
                    }
                }
            }
        }
    }

    m_atol.resize(neq());
    fill(m_atol.begin(), m_atol.end(), m_atols);
    m_integ->setTolerances(m_rtol, neq(), DATA_PTR(m_atol));
    m_integ->setSensitivityTolerances(m_rtolsens, m_atolsens);
    m_integ->setMaxStepSize(m_maxstep);
    m_integ->setMaxErrTestFails(m_maxErrTestFails);
    if (m_verbose) {
        sprintf(buf, "Number of equations: %s\n", int2str(neq()).c_str());
        writelog(buf);
        sprintf(buf, "Maximum time step:   %14.6g\n", m_maxstep);
        writelog(buf);
    }
    m_integ->initialize(m_time, *this);
    m_init = true;
}

void ReactorNet::advance(doublereal time)
{
    if (!m_init) {
        if (m_maxstep < 0.0) {
            m_maxstep = time - m_time;
        }
        initialize();
    }
    m_integ->integrate(time);
    m_time = time;
    updateState(m_integ->solution());
}

double ReactorNet::step(doublereal time)
{
    if (!m_init) {
        if (m_maxstep < 0.0) {
            m_maxstep = time - m_time;
        }
        initialize();
    }
    m_time = m_integ->step(time);
    updateState(m_integ->solution());
    return m_time;
}

void ReactorNet::addReactor(Reactor* r, bool iown)
{
    r->setNetwork(this);
    if (r->type() >= ReactorType) {
        m_reactors.push_back(r);
        m_iown.push_back(iown);
        writelog("Adding reactor "+r->name()+"\n", m_verbose);
    } else {
        writelog("Not adding reactor "+r->name()+
                 ", since type = "+int2str(r->type())+"\n", m_verbose);
    }
}

void ReactorNet::eval(doublereal t, doublereal* y,
                      doublereal* ydot, doublereal* p)
{
    size_t n;
    size_t pstart = 0;

    updateState(y);
    for (n = 0; n < m_reactors.size(); n++) {
        m_reactors[n]->evalEqs(t, y + m_start[n],
                               ydot + m_start[n], p + pstart);
        pstart += m_nparams[n];
    }
}

void ReactorNet::evalJacobian(doublereal t, doublereal* y,
                              doublereal* ydot, doublereal* p, Array2D* j)
{
    doublereal ysave, dy;
    Array2D& jac = *j;

    //evaluate the unperturbed ydot
    eval(t, y, ydot, p);
    for (size_t n = 0; n < m_nv; n++) {

        // perturb x(n)
        ysave = y[n];
        dy = m_atol[n] + fabs(ysave)*m_rtol;
        y[n] = ysave + dy;
        dy = y[n] - ysave;

        // calculate perturbed residual
        eval(t, y, DATA_PTR(m_ydot), p);

        // compute nth column of Jacobian
        for (size_t m = 0; m < m_nv; m++) {
            jac(m,n) = (m_ydot[m] - ydot[m])/dy;
        }
        y[n] = ysave;
    }
}

void ReactorNet::updateState(doublereal* y)
{
    for (size_t n = 0; n < m_reactors.size(); n++) {
        m_reactors[n]->updateState(y + m_start[n]);
    }
}

void ReactorNet::getInitialConditions(doublereal t0,
                                      size_t leny, doublereal* y)
{
    for (size_t n = 0; n < m_reactors.size(); n++) {
        m_reactors[n]->getInitialConditions(t0, m_start[n+1]-m_start[n],
                                            y + m_start[n]);
    }
}

size_t ReactorNet::globalComponentIndex(const string& component, size_t reactor)
{
    if (!m_init) {
        initialize();
    }
    return m_start[reactor] + m_reactors[reactor]->componentIndex(component);
}

void ReactorNet::registerSensitivityReaction(void* reactor,
        size_t reactionIndex, const std::string& name, int leftright)
{
    std::pair<void*, int> R = std::make_pair(reactor, leftright);
    if (m_sensOrder.count(R) &&
            m_sensOrder[R].count(reactionIndex)) {
        throw CanteraError("ReactorNet::registerSensitivityReaction",
                           "Attempted to register duplicate sensitivity reaction");
    }
    m_paramNames.push_back(name);
    m_sensOrder[R][reactionIndex] = m_ntotpar;
    m_ntotpar++;
}

}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include <QtTest>

// Don't do this at home. This is test code, not production.
#define protected public
#define private public

#include <private/qfile_p.h>

class tst_offsets : public QObject
{
    Q_OBJECT

public:
    tst_offsets() {}

private slots:
    void offsets();
    void offsets_data();
};

void tst_offsets::offsets()
{
    QFETCH(int, actual);
    QFETCH(int, expected32);
    QFETCH(int, expected64);
    int expect = sizeof(void *) == 4 ? expected32 : expected64;
    QCOMPARE(actual, expect);
}

void tst_offsets::offsets_data()
{
    QTest::addColumn<int>("actual");
    QTest::addColumn<int>("expected32");
    QTest::addColumn<int>("expected64");

    const int qtVersion = QT_VERSION;

    {
        QFilePrivate *p = 0;
        QTestData &data = QTest::newRow("File::fileName")
                << int((char *)&p->fileName - (char *)p);
        if (qtVersion >= 0x50200)
            data << 176 << 272;
        else if (qtVersion >= 0x50000)
            data << 180 << 280;
        else
            data << 140 << 232;
    }

}

QTEST_APPLESS_MAIN(tst_offsets);

#include "tst_offsets.moc"

<commit_msg>Tests: Extend tst_offset<commit_after>/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include <QtTest>

// Don't do this at home. This is test code, not production.
#define protected public
#define private public

#include <private/qfile_p.h>
#include <private/qfileinfo_p.h>

class tst_offsets : public QObject
{
    Q_OBJECT

public:
    tst_offsets() {}

private slots:
    void offsets();
    void offsets_data();
};

void tst_offsets::offsets()
{
    QFETCH(int, actual);
    QFETCH(int, expected32);
    QFETCH(int, expected64);
    int expect = sizeof(void *) == 4 ? expected32 : expected64;
    QCOMPARE(actual, expect);
}

void tst_offsets::offsets_data()
{
    QTest::addColumn<int>("actual");
    QTest::addColumn<int>("expected32");
    QTest::addColumn<int>("expected64");

    const int qtVersion = QT_VERSION;

    {
        QFilePrivate *p = 0;
        QTestData &data = QTest::newRow("File::fileName")
                << int((char *)&p->fileName - (char *)p);
        if (qtVersion >= 0x50200)
            data << 176 << 272;
        else if (qtVersion >= 0x50000)
            data << 180 << 280;
        else
            data << 140 << 232;
    }

    {
        QFileInfoPrivate *p = 0;
        QTestData &data = QTest::newRow("FileInfo::filePath")
                << int((char *)&p->fileEntry.m_filePath - (char *)p);
        data << 4 << 8;
    }
}

QTEST_APPLESS_MAIN(tst_offsets);

#include "tst_offsets.moc"

<|endoftext|>


<commit_before>
// Copyright 2010-2012 University of Washington. All Rights Reserved.
// LICENSE_PLACEHOLDER
// This software was created with Government support under DE
// AC05-76RL01830 awarded by the United States Department of
// Energy. The Government has certain rights in the software.

#include <boost/test/unit_test.hpp>
#include "Grappa.hpp"
#include "ParallelLoop.hpp"
#include "GlobalAllocator.hpp"
#include "Delegate.hpp"
#include "GlobalHashTable.hpp"
#include "GlobalHashSet.hpp"
#include "Statistics.hpp"

#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int.hpp>
#include <boost/random/variate_generator.hpp>

using namespace Grappa;

BOOST_AUTO_TEST_SUITE( GlobalHashTable_tests );

DEFINE_int64(nelems, 100, "number of elements in (large) test arrays");
DEFINE_int64(ght_size, 1024, "number of elements in (large) test arrays");
DEFINE_int64(max_key, 1<<10, "maximum random key");

DEFINE_int64(ntrials, 1, "number of independent trials to average over");

DEFINE_bool(table_perf, false, "do performance test of GlobalHashTable");
DEFINE_bool(set_perf, false, "do performance test of GlobalHashSet");

GRAPPA_DEFINE_STAT(SummarizingStatistic<double>, ght_insert_time, 0);
GRAPPA_DEFINE_STAT(SummarizingStatistic<double>, hashset_insert_time, 0);

template< typename T >
inline T next_random() {
  using engine_t = boost::mt19937_64;
  using dist_t = boost::uniform_int<T>;
  using gen_t = boost::variate_generator<engine_t&,dist_t>;

  // continue using same generator with multiple calls (to not repeat numbers)
  // but start at different seed on each node so we don't get overlap
  static engine_t engine(12345L*mycore());
  static gen_t gen(engine, dist_t(0, std::numeric_limits<T>::max()));
  return gen();
}

uint64_t kahan_hash(long k) { return k * 1299227; } // "Kahan's Hash"
uint64_t identity_hash(long k) { return k; }

enum class Exp { INSERT_UNIQUE };

template< Exp EXP,
          typename K, typename V, uint64_t (*H)(K),
          CompletionEvent* CE = &impl::local_ce,
          int64_t          TH = impl::USE_LOOP_THRESHOLD_FLAG >
double test_insert_throughput(GlobalAddress<GlobalHashTable<K,V,H>> ha) {
  double t = Grappa_walltime();

  forall_global_private<CE,TH>(0, FLAGS_nelems, [ha](int64_t i){
    if (EXP == Exp::INSERT_UNIQUE) {
      ha->insert_unique(next_random<long>());
    }
  });

  t = Grappa_walltime() - t;
  return t;
}

void test_correctness() {
  LOG(INFO) << "Testing correctness...";
  auto ha = GlobalHashTable<long,long,&identity_hash>::create(FLAGS_ght_size);
  for (int i=0; i<10; i++) {
    ha->insert(i, 42);
  }
  ha->global_set_RO();
  for (int i=0; i<10; i++) {
    GlobalAddress<long> res;
    BOOST_CHECK_EQUAL(ha->lookup(i, &res), 1);
    BOOST_CHECK_EQUAL(delegate::read(res), 42);
  }

  ha->forall_entries([](long key, BufferVector<long>& vs){ vs.setReadWriteMode(); });

  forall_global_private(10, FLAGS_nelems-10, [ha](int64_t i){
    ha->insert(i, 42);
  });
  ha->forall_entries([](long key, BufferVector<long>& vs){ vs.setReadWriteMode(); });

  ha->forall_entries([](long key, BufferVector<long>& vals){
    BOOST_CHECK_EQUAL(vals.size(), 1);
    auto a = vals.getReadBuffer();
    BOOST_CHECK_EQUAL(a.core(), mycore());
    BOOST_CHECK_EQUAL(delegate::read(a), 42);
  });

  ha->destroy();
}

void test_set_correctness() {
  LOG(INFO) << "Testing correctness of GlobalHashSet...";
  auto sa = GlobalHashSet<long,&identity_hash>::create(FLAGS_ght_size);

  for (int i=0; i<10; i++) {
    // BOOST_CHECK_EQUAL(sa->insert(i), false);
    sa->insert(42+i);
  }
  for (int i=0; i<10; i++) {
    // BOOST_CHECK_EQUAL(sa->insert(i), true);
    BOOST_CHECK_EQUAL(sa->lookup(42+i), true);
  }

  on_all_cores([sa]{
    for (int i=10; i<20; i++) {
      sa->insert(42+i);
    }
  });

  sa->forall_keys([](long& k) { BOOST_CHECK(k < 42+20 && k >= 42); });

  BOOST_CHECK_EQUAL(sa->size(), 20);
  sa->destroy();
}

double test_set_insert_throughput() {
  auto sa = GlobalHashSet<long,&identity_hash>::create(FLAGS_ght_size);

  double t = walltime();

  forall_global_private(0, FLAGS_nelems, [sa](int64_t i){
    sa->insert(next_random<long>() % FLAGS_max_key);
  });

  t = walltime() - t;

  VLOG(1) << "set_size: " << sa->size();
  sa->destroy();
  return t;
}

void user_main( void * ignore ) {
  if (FLAGS_table_perf) {
    auto ha = GlobalHashTable<long,long,&kahan_hash>::create(FLAGS_ght_size);

    for (int i=0; i<FLAGS_ntrials; i++) {
      ght_insert_time += test_insert_throughput<Exp::INSERT_UNIQUE>(ha);
    }

    ha->destroy();

  } else if (FLAGS_set_perf) {
    for (int i=0; i<FLAGS_ntrials; i++) {
      hashset_insert_time += test_set_insert_throughput();
    }
  } else {
    test_correctness();
    test_set_correctness();
  }

  Statistics::merge_and_print();
}

BOOST_AUTO_TEST_CASE( test1 ) {
  Grappa_init( &(boost::unit_test::framework::master_test_suite().argc),
                &(boost::unit_test::framework::master_test_suite().argv) );
  Grappa_activate();
  Grappa_run_user_main( &user_main, (void*)NULL );
  Grappa_finish( 0 );
}

BOOST_AUTO_TEST_SUITE_END();

<commit_msg>Rename flag to global_hash_size (for Set and Table)<commit_after>
// Copyright 2010-2012 University of Washington. All Rights Reserved.
// LICENSE_PLACEHOLDER
// This software was created with Government support under DE
// AC05-76RL01830 awarded by the United States Department of
// Energy. The Government has certain rights in the software.

#include <boost/test/unit_test.hpp>
#include "Grappa.hpp"
#include "ParallelLoop.hpp"
#include "GlobalAllocator.hpp"
#include "Delegate.hpp"
#include "GlobalHashTable.hpp"
#include "GlobalHashSet.hpp"
#include "Statistics.hpp"

#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int.hpp>
#include <boost/random/variate_generator.hpp>

using namespace Grappa;

BOOST_AUTO_TEST_SUITE( GlobalHashTable_tests );

DEFINE_int64(nelems, 100, "number of elements in (large) test arrays");
DEFINE_int64(global_hash_size, 1024, "number of elements in (large) test arrays");
DEFINE_int64(max_key, 1<<10, "maximum random key");

DEFINE_int64(ntrials, 1, "number of independent trials to average over");

DEFINE_bool(table_perf, false, "do performance test of GlobalHashTable");
DEFINE_bool(set_perf, false, "do performance test of GlobalHashSet");

GRAPPA_DEFINE_STAT(SummarizingStatistic<double>, ght_insert_time, 0);
GRAPPA_DEFINE_STAT(SummarizingStatistic<double>, hashset_insert_time, 0);

template< typename T >
inline T next_random() {
  using engine_t = boost::mt19937_64;
  using dist_t = boost::uniform_int<T>;
  using gen_t = boost::variate_generator<engine_t&,dist_t>;

  // continue using same generator with multiple calls (to not repeat numbers)
  // but start at different seed on each node so we don't get overlap
  static engine_t engine(12345L*mycore());
  static gen_t gen(engine, dist_t(0, std::numeric_limits<T>::max()));
  return gen();
}

uint64_t kahan_hash(long k) { return k * 1299227; } // "Kahan's Hash"
uint64_t identity_hash(long k) { return k; }

enum class Exp { INSERT_UNIQUE };

template< Exp EXP,
          typename K, typename V, uint64_t (*H)(K),
          CompletionEvent* CE = &impl::local_ce,
          int64_t          TH = impl::USE_LOOP_THRESHOLD_FLAG >
double test_insert_throughput(GlobalAddress<GlobalHashTable<K,V,H>> ha) {
  double t = Grappa_walltime();

  forall_global_private<CE,TH>(0, FLAGS_nelems, [ha](int64_t i){
    if (EXP == Exp::INSERT_UNIQUE) {
      ha->insert_unique(next_random<long>());
    }
  });

  t = Grappa_walltime() - t;
  return t;
}

void test_correctness() {
  LOG(INFO) << "Testing correctness...";
  auto ha = GlobalHashTable<long,long,&identity_hash>::create(FLAGS_global_hash_size);
  for (int i=0; i<10; i++) {
    ha->insert(i, 42);
  }
  ha->global_set_RO();
  for (int i=0; i<10; i++) {
    GlobalAddress<long> res;
    BOOST_CHECK_EQUAL(ha->lookup(i, &res), 1);
    BOOST_CHECK_EQUAL(delegate::read(res), 42);
  }

  ha->forall_entries([](long key, BufferVector<long>& vs){ vs.setReadWriteMode(); });

  forall_global_private(10, FLAGS_nelems-10, [ha](int64_t i){
    ha->insert(i, 42);
  });
  ha->forall_entries([](long key, BufferVector<long>& vs){ vs.setReadWriteMode(); });

  ha->forall_entries([](long key, BufferVector<long>& vals){
    BOOST_CHECK_EQUAL(vals.size(), 1);
    auto a = vals.getReadBuffer();
    BOOST_CHECK_EQUAL(a.core(), mycore());
    BOOST_CHECK_EQUAL(delegate::read(a), 42);
  });

  ha->destroy();
}

void test_set_correctness() {
  LOG(INFO) << "Testing correctness of GlobalHashSet...";
  auto sa = GlobalHashSet<long,&identity_hash>::create(FLAGS_global_hash_size);

  for (int i=0; i<10; i++) {
    // BOOST_CHECK_EQUAL(sa->insert(i), false);
    sa->insert(42+i);
  }
  for (int i=0; i<10; i++) {
    // BOOST_CHECK_EQUAL(sa->insert(i), true);
    BOOST_CHECK_EQUAL(sa->lookup(42+i), true);
  }

  on_all_cores([sa]{
    for (int i=10; i<20; i++) {
      sa->insert(42+i);
    }
  });

  sa->forall_keys([](long& k) { BOOST_CHECK(k < 42+20 && k >= 42); });

  BOOST_CHECK_EQUAL(sa->size(), 20);
  sa->destroy();
}

double test_set_insert_throughput() {
  auto sa = GlobalHashSet<long,&identity_hash>::create(FLAGS_global_hash_size);

  double t = walltime();

  forall_global_private(0, FLAGS_nelems, [sa](int64_t i){
    sa->insert(next_random<long>() % FLAGS_max_key);
  });

  t = walltime() - t;

  VLOG(1) << "set_size: " << sa->size();
  sa->destroy();
  return t;
}

void user_main( void * ignore ) {
  if (FLAGS_table_perf) {
    auto ha = GlobalHashTable<long,long,&kahan_hash>::create(FLAGS_global_hash_size);

    for (int i=0; i<FLAGS_ntrials; i++) {
      ght_insert_time += test_insert_throughput<Exp::INSERT_UNIQUE>(ha);
    }

    ha->destroy();

  } else if (FLAGS_set_perf) {
    for (int i=0; i<FLAGS_ntrials; i++) {
      hashset_insert_time += test_set_insert_throughput();
    }
  } else {
    test_correctness();
    test_set_correctness();
  }

  Statistics::merge_and_print();
}

BOOST_AUTO_TEST_CASE( test1 ) {
  Grappa_init( &(boost::unit_test::framework::master_test_suite().argc),
                &(boost::unit_test::framework::master_test_suite().argv) );
  Grappa_activate();
  Grappa_run_user_main( &user_main, (void*)NULL );
  Grappa_finish( 0 );
}

BOOST_AUTO_TEST_SUITE_END();

<|endoftext|>