text:
//--------------------------------------------------------------------//
// Digital Scenario Framework                                         //
//  by Giovanni Paolo Vigano', 2021                                   //
//--------------------------------------------------------------------//
//
// Distributed under the MIT Software License.
// See http://opensource.org/licenses/MIT
//

#include <SimplECircuitCybSys/SimplECircuitCybSys.h>
#include <SimplECircuitCybSys/SimplECircuitSolver.h>

#include <discenfw/xp/EnvironmentModel.h>
#include <discenfw/util/MessageLog.h>

#include <boost/config.hpp> // for BOOST_SYMBOL_EXPORT

#include <iostream>
#include <sstream>

using namespace discenfw::xp;

namespace
{
	inline std::string BoolToString(bool val) { return val ? "true" : "false"; }
}

namespace simplecircuit_cybsys
{

	SimplECircuitCybSys::SimplECircuitCybSys()
	{
		Circuit = std::make_unique<simplecircuit_cybsys::ElectronicCircuit>();
	}

	void SimplECircuitCybSys::CreateEntityStateTypes()
	{
		if (ComponentEntityType)
		{
			return;
		}

		ComponentEntityType = CreateEntityStateType(
			"",
			"Electronic Component",
			{
				{"connections","0"},
				{"connected","false"},
				{"burnt out","false"},
			},
			{
				{ "connected", { "true","false" } },
				{"burnt out", { "true","false" }},
			},
			{}
			);

		ResistorEntityType = CreateEntityStateType(
			"Electronic Component",
			"Resistor",
			{
			},
			{
				{"connections",{"0","1","2"}},
			},
			{ "Pin1", "Pin2" }
			);

		LedEntityType = CreateEntityStateType(
			"Electronic Component",
			"LED",
			{
				{"lit up","false"},
			},
			{
				{"connections",{"0","1","2"}},
				{ "lit up", { "true","false" } },
			},
			{ "Anode", "Cathode" }
			);

		PowerEntityType = CreateEntityStateType(
			"Electronic Component",
			"Power Supply",
			{
			},
			{
				{"connections",{"0","1","2"}},
			},
			{ "+", "-" }
			);

		SwitchEntityType = CreateEntityStateType(
			"Electronic Component",
			"Switch",
			{
				{"position","0"},
			},
			{
				{"connections",{"0","1","2","3"}},
				{ "position", { "0","1" } },
			},
			{ "In", "Out0", "Out1" }
		);
	}

	void SimplECircuitCybSys::ClearSystem()
	{
		Circuit->Components.clear();
	}

	void SimplECircuitCybSys::InitFailureConditions()
	{
		// set a default failure condition (any component burnt out)
		PropertyCondition burntOutCond({ "burnt out",BoolToString(true) });
		Condition anyBurntOut({ {EntityCondition::ANY,{burntOutCond}} });
		FailureCondition = anyBurntOut;
	}

	void SimplECircuitCybSys::InitRoles()
	{
		std::shared_ptr<EnvironmentModel> model = GetModel();
		if (model->GetRoleNames().empty())
		{
			PropertyCondition burntOutCond({ "burnt out",BoolToString(true) });
			Condition anyBurntOut({ { EntityCondition::ANY,{ burntOutCond } } });
			xp::SetRole(
				"Default",
				{}, // SuccessCondition
				{}, // FailureCondition
				{}, // DeadlockCondition
				{
					// ResultReward
					{
						{ ActionResult::IN_PROGRESS,0 },
						{ ActionResult::SUCCEEDED,1000 },
						{ ActionResult::FAILED,-1000 },
						{ ActionResult::DEADLOCK,-10 },
					},
				// PropertyCountRewards
					{},
				// EntityConditionRewards
					{
					},
					// FeatureRewards
					{
					}
				}
				);
		}
	}

	void SimplECircuitCybSys::ResetSystem()
	{
		Circuit->Reset();
	}

	bool SimplECircuitCybSys::ExecuteAction(const Action& action)
	{
		enum ActionId { CONNECT, SWITCH, DISCONNECT };
		static std::map<std::string, ActionId> actionNames{
			{ "connect",CONNECT },
			{ "switch",SWITCH },
			{ "disconnect",DISCONNECT },
		};
		switch (actionNames[action.TypeId])
		{
		case CONNECT:
			return DoConnectAction(action);
		case SWITCH:
			return DoSwitchAction(action);
		case DISCONNECT:
			return DoDisconnectAction(action);
		default:
			break;
		}
		return false;
	}

	void SimplECircuitCybSys::SynchronizeState(std::shared_ptr<xp::EnvironmentState> environmentState)
	{
		// TODO: alternative: just update existing entities and remove dangling entities?
		environmentState->Clear();

		// synchronize component states
		for (const auto& comp : Circuit->Components)
		{
			std::string entityId = comp.first;
			const auto& component = comp.second;
			std::shared_ptr<Led> led = AsLed(component);
			std::shared_ptr<Switch> sw = AsSwitch(component);
			std::shared_ptr<PowerSupplyDC> powerSupply = AsPowerSupplyDC(component);
			std::shared_ptr<Resistor> resistor = AsResistor(component);

			// get the properties of the current component
			bool nowBurnt = component->BurntOut;
			bool nowConnected = component->Connected;
			int nowConn = component->GetConnectedLeadsCount();
			bool nowLit = led && led->LitUp;
			int nowPos = (int)(sw && sw->Position == SwitchPosition::POS1);

			// update the entity state for the current component
			std::shared_ptr<EntityState> entState = environmentState->GetEntityState(entityId);
			if (!entState)
			{
				std::shared_ptr<EntityStateType> entType;

				if (!ComponentEntityType)
				{
					CreateEntityStateTypes();
				}

				if (powerSupply) entType = PowerEntityType;
				else if (led) entType = LedEntityType;
				else if (sw) entType = SwitchEntityType;
				else if (resistor) entType = ResistorEntityType;
				//else if (transistor) entType = TransistorEntityType;
				else entType = ComponentEntityType;

				entState = EntityState::Make(entType->GetTypeName(),entType->GetModelName());
				//entState = std::make_shared<EntityState>(entType->GetTypeName(),entType->GetModelName());
				environmentState->SetEntityState(entityId, entState);
			}

			std::vector< std::pair<std::string, std::shared_ptr<ElectronicComponentLead> >> leads;
			component->GetLeads(leads);

			// store new component relationships
			for (const auto& eLead : leads)
			{
				if (!eLead.second->Connections.empty())
				{
					RelationshipLink link;
					link.EntityId = eLead.second->Connections[0].Component;
					link.LinkId = eLead.second->Connections[0].Lead;
					entState->SetRelationship(eLead.first, link);
				}
				else
				{
					entState->RemoveRelationship(eLead.first);
				}
			}

			// set the properties for the entity state
			entState->SetPropertyValue("burnt out", BoolToString(nowBurnt));
			entState->SetPropertyValue("connected", BoolToString(nowConnected));
			entState->SetPropertyValue("connections", std::to_string(nowConn));

			if (led)
			{
				entState->SetPropertyValue("lit up", BoolToString(nowLit));
			}

			if (sw)
			{
				entState->SetPropertyValue("position", std::to_string(nowPos));
			}

			if (LogEnabled)
			{
				if (nowBurnt)
				{
					LogStream << entityId << " => burnt out" << std::endl;
					FlushLog(LOG_DEBUG);
				}
				if (nowLit)
				{
					LogStream << entityId << " => lit up" << std::endl;
					FlushLog(LOG_DEBUG);
				}

				if (nowPos)
				{
					LogStream << entityId << " => on" << std::endl;
					FlushLog(LOG_DEBUG);
				}
			}
		}
	}

	const std::vector<ActionRef>& SimplECircuitCybSys::GetAvailableActions(
		const std::string& roleId,
		bool smartSelection
		) const
	{
		CachedAvailableActions.clear();
		std::shared_ptr<PowerSupplyDC> powerSupply = Circuit->GetPowerSupply();
		bool circuitIsComplete = false;
		if (smartSelection)
		{
			if(powerSupply && powerSupply->GetConnectedLeadsCount()==2)
			{
				circuitIsComplete = true;
				for (const auto& compItem : Circuit->Components)
				{
					// Check if at least one component is connected but not fully connected
					// (power supply was already checked)
					if (compItem.second != powerSupply && compItem.second->GetConnectedLeadsCount() == 1)
					{
						circuitIsComplete = false;
						break;
					}
				}
			}
		}

		std::vector<std::string> actionNames{ "connect", "switch" };
		for (const auto& compItem : Circuit->Components)
		{
			std::string compId = compItem.first;
			std::shared_ptr<ElectronicComponent> component = compItem.second;
			bool powerSupplyConnected = powerSupply && powerSupply->AnyLeadConnected();
			std::string powerId = Circuit->GetComponentName(powerSupply);
			if (!component->BurntOut)
			{
				auto sw = AsSwitch(component);

				if (sw)
				{
					bool canBeSwitched = true;
					if (smartSelection)
					{
						canBeSwitched = circuitIsComplete && sw->GetConnectedLeadsCount() > 1 && sw->Lead("In")->Connected();
					}
					// possible deadlock: repeatedly switching --> deadlock detection required
					if (canBeSwitched)
					{
						CacheAvailableAction(
							{ "switch",{ compId,sw->Position == SwitchPosition::POS0 ? "1" : "0" } }
							);
					}
					// alternative solution:
					// allow switch-on only, this avoids possible deadlocks
					//if (canBeSwitched && sw->Position == SwitchPosition::POS0)
					//...
				}

				// if (!component->AllLeadsConnected()) ...

				// allow only 2 connections per component to simplify the circuit simulation
				if (component->GetConnectedLeadsCount() < 2)
				{
					std::vector< std::shared_ptr<ElectronicComponentLead> > leads;
					std::vector< std::string > leadNames;
					component->GetLeads(leads);
					component->GetLeadNames(leadNames);
					for (const auto& otherCompItem : Circuit->Components)
					{
						std::string otherCompId = otherCompItem.first;
						std::shared_ptr<ElectronicComponent> otherComponent = otherCompItem.second;
						bool connectingPowerSupply = (otherComponent == powerSupply || component == powerSupply);
						bool connectedToPowerSupply = (otherComponent->Connected || component->Connected);
						bool canBeConnected =
							(!otherComponent->BurntOut
								&& otherComponent != component
								&& !otherComponent->AllLeadsConnected()
								&& !component->ConnectedTo(otherCompId)
								);
						if (smartSelection)
						{
							canBeConnected = canBeConnected && (connectingPowerSupply || connectedToPowerSupply);
						}
						if (canBeConnected)
						{
							std::vector< std::shared_ptr<ElectronicComponentLead> > otherLeads;
							std::vector< std::string > otherLeadNames;
							otherComponent->GetLeads(otherLeads);
							otherComponent->GetLeadNames(otherLeadNames);
							for (size_t i = 0; i < leads.size(); i++)
							{
								const auto& lead = leads[i];
								// allow only 1 connection per lead to simplify the circuit simulation
								if (!lead->Connected())
								{
									for (size_t j = 0; j < otherLeads.size(); j++)
									{
										const auto& otherLead = otherLeads[j];

										if (!otherLead->Connected())
										{
											// prevent parallel connections of components to simplify the circuit simulation
											//if (otherLead != lead && !otherLead->ConnectedTo(compId, leadNames[i]))
											if (otherLead != lead && !otherLead->ConnectedTo(compId))
											{
												CacheAvailableAction(
													{ "connect",
														{
															compId, leadNames[i],
															otherCompId, otherLeadNames[j]
														}
													}
													);
											}
										}
									}
								}
							}
						}
					}
				}
			}
		}

		return CachedAvailableActions;
	}

	bool SimplECircuitCybSys::DoConnectAction(const Action& action)
	{
		// decode parameters
		const std::string& component1Id = action.Params[0];
		const std::string& lead1Id = action.Params[1];
		const std::string& component2Id = action.Params[2];
		const std::string& lead2Id = action.Params[3];

		// prevent connecting a lead with itself
		if (component1Id == component2Id && lead1Id == lead2Id)
		{
			return false;
		}

		std::shared_ptr<ElectronicComponent> component1 = Circuit->FindComponent(component1Id);
		std::shared_ptr<ElectronicComponent> component2 = Circuit->FindComponent(component2Id);

		// check if components exist
		if (!component1 || !component2)
		{
			return false;
		}

		// check if already connected
		if (component1->ConnectedTo(component2Id, lead2Id))
		{
			return false;
		}

		// allow only 1 connection per lead to simplify the circuit simulation
		if (component1->Lead(lead1Id)->Connected() || component2->Lead(lead2Id)->Connected())
		{
			return false;
		}

		if (LogEnabled)
		{
			LogStream << "> " << component1Id << "/" << lead1Id
				<< " <--> " << component2Id << "/" << lead2Id << std::endl;
			FlushLog(LOG_DEBUG);
		}

		// update the circuit
		Circuit->Connect(component1Id, lead1Id, component2Id, lead2Id);
		SolveElectronicCircuit(*Circuit);

		return true;
	}

	bool SimplECircuitCybSys::DoSwitchAction(const Action& action)
	{
		// decode parameters
		const std::string& switchId = action.Params[0];
		const std::string& posId = action.Params[1];
		bool pos = std::atoi(posId.c_str()) > 0;

		auto sw = AsSwitch(Circuit->FindComponent(switchId));
		if (!sw)
		{
			return false;
		}

		if (LogEnabled)
		{
			LogStream << std::noboolalpha << "> " << switchId << ": " << pos << std::endl;
			FlushLog(LOG_DEBUG);
		}

		// update the circuit
		sw->Position = (SwitchPosition)pos;
		SolveElectronicCircuit(*Circuit);
		return true;
	}

	bool SimplECircuitCybSys::DoDisconnectAction(const Action& action)
	{
		size_t numParams = action.Params.size();
		if(numParams!=2 && numParams!=4)
		{
			return false;
		}

		// decode parameters
		const std::string& component1Id = action.Params[0];
		const std::string& lead1Id = action.Params[1];
		std::shared_ptr<ElectronicComponent> component1 = Circuit->FindComponent(component1Id);

		if (!component1->Lead(lead1Id)->Connected())
		{
			return false;
		}
		if (numParams == 2)
		{
			// update the circuit
			Circuit->Disconnect(component1Id, lead1Id);
		}
		else //if (numParams == 4)
		{
			const std::string& component2Id = action.Params[2];
			const std::string& lead2Id = action.Params[3];

			// prevent connecting a lead with itself
			if (component1Id == component2Id && lead1Id == lead2Id)
			{
				return false;
			}

			std::shared_ptr<ElectronicComponent> component2 = Circuit->FindComponent(component2Id);

			// check if components exist
			if (!component1 || !component2)
			{
				return false;
			}

			// check if already connected
			if (!component1->ConnectedTo(component2Id, lead2Id))
			{
				return false;
			}

			if (!component2->Lead(lead2Id)->Connected())
			{
				return false;
			}

			if (LogEnabled)
			{
				LogStream << "> " << component1Id << "/" << lead1Id
					<< " X--X " << component2Id << "/" << lead2Id << std::endl;
				FlushLog(LOG_DEBUG);
			}

			// update the circuit
			Circuit->Disconnect(component1Id, lead1Id, component2Id, lead2Id);
		}
		SolveElectronicCircuit(*Circuit);

		return true;
	}

	std::shared_ptr<ElectronicComponent> SimplECircuitCybSys::CreateComponentFromConfiguration(
		const std::string& config, std::string& compId)
	{
		std::istringstream iStr(config);

		if (!iStr.good())
		{
			return nullptr;
		}
		std::shared_ptr<ElectronicComponent> comp;

		std::string compType;

		iStr >> compType >> compId;
		comp = MakeComponent(compType);

		if (comp)
		{
			ReadComponentConfiguration(iStr, comp);
			Circuit->Components[compId] = comp;
		}
		return comp;
	}

	const std::string SimplECircuitCybSys::GetComponentConfiguration(const std::string& compId)
	{
		std::shared_ptr<ElectronicComponent> comp = Circuit->FindComponent(compId);
		if (!comp)
		{
			return "";
		}
		std::ostringstream oStr;
		std::shared_ptr<Led> led = AsLed(comp);
		if (led)
		{
			oStr << led->Type->Name;
		}
		std::shared_ptr<Resistor> r = AsResistor(comp);
		if (r)
		{
			oStr << r->Ohm
				<< " " << r->Max_mW;
		}
		std::shared_ptr<Switch> sw = AsSwitch(comp);
		if (sw)
		{
			oStr << sw->MaxVoltage_mV
				<< " " << sw->MaxCurrent_mA;
		}
		std::shared_ptr<PowerSupplyDC> powerSupply = AsPowerSupplyDC(comp);
		if (powerSupply)
		{
			oStr << powerSupply->Voltage_mV
				<< " " << powerSupply->MaxCurrent_mA;
		}
		return oStr.str();
	}

	bool SimplECircuitCybSys::SetComponentConfiguration(const std::string& compId, const std::string& config)
	{
		std::shared_ptr<ElectronicComponent> comp = Circuit->FindComponent(compId);
		if (!comp)
		{
			return false;
		}
		std::istringstream iStr(config);
		ReadComponentConfiguration(iStr, comp);
		return true;
	}

	bool SimplECircuitCybSys::SetConfiguration(const std::string& config)
	{
		Initialize();
		Circuit->Components.clear();
		bool firstRead = true;
		std::istringstream iStr(config);
		while (iStr.good())
		{
			std::string compConfig;
			std::getline(iStr, compConfig);
			std::string compId;
			std::shared_ptr<ElectronicComponent> comp = CreateComponentFromConfiguration(
				compConfig, compId);
			if (firstRead &&!comp)
			{
				return false;
			}
			firstRead = false;
		}
		Initialize(true);
		return true;
	}

	const std::string SimplECircuitCybSys::GetConfiguration()
	{
		std::ostringstream oStr;
		for (const auto& comp : Circuit->Components)
		{
			oStr << comp.second->GetTypeName()
				<< " " << comp.first << " ";
			oStr << GetComponentConfiguration(comp.first);
			oStr << "\n";
		}
		return oStr.str();
	}

	const std::string SimplECircuitCybSys::ReadEntityConfiguration(const std::string& entityId)
	{
		return GetComponentConfiguration(entityId);
	}

	bool SimplECircuitCybSys::WriteEntityConfiguration(const std::string& entityId, const std::string& config)
	{
		return SetComponentConfiguration(entityId, config);
	}

	bool SimplECircuitCybSys::ConfigureEntity(const std::string& entityId, const std::string& entityType, const std::string& config)
	{
		std::shared_ptr<ElectronicComponent> comp;
		if (Circuit->Components.find(entityId) != Circuit->Components.end())
		{
			comp = Circuit->Components[entityId];
			if (comp->GetTypeName() != entityType)
			{
				Circuit->Components.erase(entityId);
				comp = nullptr;
			}
		}

		if (!comp)
		{
			comp = MakeComponent(entityType);
			if (!comp)
			{
				return false;
			}
			Circuit->Components[entityId] = comp;
		}
		std::istringstream iStr(config);
		ReadComponentConfiguration(iStr, comp);
		return true;
	}

	bool SimplECircuitCybSys::RemoveEntity(const std::string& entityId)
	{
		if (Circuit->Components.find(entityId) != Circuit->Components.end())
		{
			std::shared_ptr<ElectronicComponent> comp = Circuit->Components[entityId];
			Circuit->Disconnect(entityId);
			Circuit->Components.erase(entityId);
			return true;
		}
		return false;
	}

	const std::string SimplECircuitCybSys::GetSystemInfo(const std::string& infoId) const
	{
		std::ostringstream oStr;
		if (infoId == "" || infoId == "CircuitSchema")
		{
			// create a schematic representation of the circuit in one text line

			std::shared_ptr<PowerSupplyDC> powerSupply = Circuit->GetPowerSupply();
			if (!powerSupply) return "";
			std::shared_ptr<ElectronicComponentLead> posLead = powerSupply->GetPositiveLead();
			std::shared_ptr<ElectronicComponentLead> negLead = powerSupply->GetNegativeLead();
			if (!posLead->Connected() || !negLead->Connected()) return "";
			int connectedComponents = 0;
			for (const auto& comp : Circuit->Components)
			{
				if (comp.second->GetConnectedLeadsCount() > 1) connectedComponents++;
			}

			std::vector<std::string> foundComponents;
			bool closedCircuit = Circuit->GetCircuitComponents(foundComponents);
			oStr << " (+)-";
			for (std::string compName : foundComponents)
			{
				const auto& comp = Circuit->Components[compName];
				const auto& sw = AsSwitch(comp);
				const auto& led = AsLed(comp);
				oStr << "-{" << compName;
				if (led && led->LitUp) oStr << "*";
				if (sw && sw->Position == SwitchPosition::POS0)	oStr << "o";
				if (sw && sw->Position == SwitchPosition::POS1)	oStr << "*";
				oStr << "}-";
			}

			if (closedCircuit) oStr << "-(-) {" << connectedComponents << "}";
		}
		else if (infoId == "CircuitInfo")
		{
			// List circuit components and their state

			for (const auto& compPair : Circuit->Components)
			{
				const auto& component = compPair.second;
				if (component->GetConnectedLeadsCount() > 1)
				{
					oStr << compPair.first;
					const auto& sw = AsSwitch(component);
					if (sw)	oStr << "#" << (int)sw->Position;
					const auto& led = AsLed(component);
					if (led && led->LitUp) oStr << "*";
					if (component->BurntOut)
					{
						oStr << "[burnt out]";
					}
					std::vector< std::shared_ptr<ElectronicComponentLead> > leads;
					component->GetLeads(leads);
					if (!leads.empty())
					{
						oStr << "@";
					}
					bool first = true;
					for (const auto& connLead : leads)
					{
						if (connLead->Connected())
						{
							if (!first) oStr << ",";
							first = false;
							oStr << connLead->Name << ">" << connLead->Connections[0].Component
								<< "." << connLead->Connections[0].Lead;
						}
					}
					oStr << " ";
				}
			}
		}

		std::string info = oStr.str();
		return info;
	}

	void SimplECircuitCybSys::ReadComponentConfiguration(std::istringstream& iStr, std::shared_ptr<ElectronicComponent> comp)
	{
		std::shared_ptr<Led> led = AsLed(comp);
		if (led)
		{
			std::string ledType;
			iStr >> ledType;
			led->Type = GetLedType(ledType);
			if (!led->Type)
			{
				LogStream << "Unknown LED type: " << ledType << std::endl;
				FlushLog(LOG_ERROR);
			}

		}
		std::shared_ptr<Resistor> r = AsResistor(comp);
		if (r)
		{
			iStr >> r->Ohm >> r->Max_mW;
		}
		std::shared_ptr<Switch> sw = AsSwitch(comp);
		if (sw)
		{
			iStr >> sw->MaxVoltage_mV >> sw->MaxCurrent_mA;
		}
		std::shared_ptr<PowerSupplyDC> powerSupply = AsPowerSupplyDC(comp);
		if (powerSupply)
		{
			iStr >> powerSupply->Voltage_mV >> powerSupply->MaxCurrent_mA;
		}

	}

	std::shared_ptr<ElectronicComponent> SimplECircuitCybSys::MakeComponent(const std::string& compType)
	{
		std::shared_ptr<ElectronicComponent> comp;
		if (compType == "PowerSupplyDC")
		{
			comp = std::make_shared<PowerSupplyDC>();
		}
		else if (compType == "LED")
		{
			comp = std::make_shared<Led>(nullptr);
		}
		else if (compType == "Resistor")
		{
			comp = std::make_shared<Resistor>();
		}
		else if (compType == "Switch")
		{
			comp = std::make_shared<Switch>();
		}
		return comp;
	}

	extern "C" BOOST_SYMBOL_EXPORT SimplECircuitCybSys CyberSystem;
	SimplECircuitCybSys CyberSystem;

} // namespace simplecircuit_cybsys

max_stars_repo_name: gpvigano/DigitalScenarioFramework

max_issues_repo_name: gpvigano/DigitalScenarioFramework

max_forks_repo_name: gpvigano/DigitalScenarioFramework


text:
/*=============================================================================
    Copyright (c) 2010 Christopher Schmidt
    Copyright (c) 2001-2011 Joel de Guzman

    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)
==============================================================================*/

#ifndef BOOST_FUSION_ALGORITHM_ITERATION_REVERSE_FOLD_HPP
#define BOOST_FUSION_ALGORITHM_ITERATION_REVERSE_FOLD_HPP

#include <boost/fusion/algorithm/iteration/reverse_fold_fwd.hpp>
#include <boost/config.hpp>
#include <boost/fusion/sequence/intrinsic/begin.hpp>
#include <boost/fusion/sequence/intrinsic/end.hpp>
#include <boost/fusion/sequence/intrinsic/empty.hpp>
#include <boost/fusion/sequence/intrinsic/size.hpp>
#include <boost/fusion/support/is_segmented.hpp>
#include <boost/fusion/iterator/equal_to.hpp>
#include <boost/fusion/iterator/deref.hpp>
#include <boost/fusion/iterator/value_of.hpp>
#include <boost/fusion/iterator/prior.hpp>
#include <boost/fusion/iterator/next.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/utility/result_of.hpp>
#include <boost/type_traits/add_const.hpp>
#include <boost/type_traits/add_reference.hpp>

#define BOOST_FUSION_REVERSE_FOLD

#if !defined(BOOST_FUSION_DONT_USE_PREPROCESSED_FILES)
#include <boost/fusion/algorithm/iteration/detail/preprocessed/reverse_fold.hpp>
#else
#if defined(__WAVE__) && defined(BOOST_FUSION_CREATE_PREPROCESSED_FILES)
#pragma wave option(preserve: 2, line: 0, output: "detail/preprocessed/reverse_fold.hpp")
#endif

/*=============================================================================
    Copyright (c) 2009-2010 Christopher Schmidt
    Copyright (c) 2001-2011 Joel de Guzman

    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)

    This is an auto-generated file. Do not edit!
==============================================================================*/

#if defined(__WAVE__) && defined(BOOST_FUSION_CREATE_PREPROCESSED_FILES)
#pragma wave option(preserve: 1)
#endif

#include <boost/fusion/algorithm/iteration/detail/fold.hpp>

#if defined(__WAVE__) && defined(BOOST_FUSION_CREATE_PREPROCESSED_FILES)
#pragma wave option(output: null)
#endif

#endif // BOOST_FUSION_DONT_USE_PREPROCESSED_FILES

#undef BOOST_FUSION_REVERSE_FOLD

#endif

ext: hpp

max_stars_repo_name: randolphwong/mcsema

max_issues_repo_name: randolphwong/mcsema

max_forks_repo_name: randolphwong/mcsema


text:
#include <Eigen/Dense>
using Eigen::MatrixXf;

#define SGA_USE_EIGEN
#include <sga.hpp>
#include "../common/common.hpp"

#include "../common/json.hpp"
using json = nlohmann::json;

#define STB_IMAGE_IMPLEMENTATION
#include "../common/stb_image.h"

#include <iostream>
#include <fstream>
#include <cassert>

inline bool file_exists(std::string path) {
  return std::ifstream(path).good();
}

void usage(char** argv){
  std::cout << "USAGE: " << argv[0] << " CONFIG_FILE" << std::endl;
}

Eigen::Matrix3f find_homography(std::vector<Eigen::Vector2f> points1, std::vector<Eigen::Vector2f> points2){
  assert(points1.size() == points2.size());
  Eigen::MatrixXf A = Eigen::MatrixXf::Zero(points1.size()*2,9);
  for(unsigned int i = 0; i < points1.size(); i++){
    float x1 = points1[i](0), y1 = points1[i](1);
    float x2 = points2[i](0), y2 = points2[i](1);
    Eigen::Matrix<float, 2, 9> Q;
    Q <<
      x1, y1, 1,  0,  0, 0, -x1*x2, -y1*x2, -x2,
      0 , 0 , 0, x1, y1, 1, -x1*y2, -y1*y2, -y2;
    A.block(i*2,0,2,9) = Q;
  }

  Eigen::JacobiSVD<Eigen::MatrixXf> svd(A, Eigen::ComputeThinU | Eigen::ComputeFullV);
  unsigned int P = svd.matrixV().cols();
  Eigen::Map<const Eigen::Matrix3f> view(svd.matrixV().block(0,P-1,9,1).data(), 3, 3);
  Eigen::Matrix3f H = view.transpose() / view(2,2);

  return H;
}

int main(int argc, char** argv){
  if(argc < 2) {
    usage(argv);
    return 1;
  }
  std::string config_path = argv[1];
  size_t q = config_path.find_last_of("/\\");
  std::string config_dir = config_path.substr(0,q);
  std::string output_path = "output.png";

  // Enable sga
  sga::init();
  renderdoc_tryenable();
  renderdoc_capture_start();

  // Open and parse config file
  std::ifstream config_file(config_path);
  if(!config_file.good()){
    std::cout << "Failed to open file \"" << config_path << "\"" << std::endl;
    return 1;
  }
  std::vector<std::string> image_paths;
  std::vector<std::pair<std::vector<Eigen::Vector2f>, std::vector<Eigen::Vector2f>>> points;
  unsigned int center = 0;
  unsigned int N;
  bool render_lines = false;
  try{
    json config;
    config_file >> config;
    auto images = config["images"];
    if(!images.is_array()){
      std::cout << "Json config must contain an array of strings \"images\" representing a list of input images." << std::endl;
      return 1;
    }
    for(auto& q : images){
      image_paths.push_back(q);
    }
    N = image_paths.size();
    if(config.count("center") > 0){
      center = config["center"];
    }
    if(config.count("lines") > 0){
      render_lines = config["lines"] != 0;
    }
    auto pointlist = config["points"];
    if(!pointlist.is_array() || pointlist.size() != N-1){
      std::cout << "Json config must contain an array of point coordinates \"points\" of the lentgh equal to the number of images minus one (" << N-1 << ")." << std::endl;
      return 1;
    }
    for(auto& pointspair : pointlist){
      std::vector<Eigen::Vector2f> pl;
      std::vector<Eigen::Vector2f> pr;
      if(pointspair.size() != 2){
        std::cout << "Each entry in \"points\" array must have two elements (a list of points in image N and a list of corresponding points on image N+1)" << std::endl;
        return 1;
      }
      for(auto& point : pointspair[0]){
        Eigen::Vector2f p;
        if(point.size() != 2){
          std::cout << "Each point must be an array of 2 numbers." << std::endl;
          return 1;
        }
        p(0) = point[0]; p(1) = point[1];
        pl.push_back(p);
      }
      for(auto& point : pointspair[1]){
        Eigen::Vector2f p;
        if(point.size() != 2){
          std::cout << "Each point must be an array of 2 numbers." << std::endl;
          return 1;
        }
        p(0) = point[0]; p(1) = point[1];
        pr.push_back(p);
      }
      points.push_back(std::make_pair(pl,pr));
    }
  }catch (json::exception& e){
    std::cout << "Error reading json config: " << e.what() << std::endl;
  }

  // Print out configuration
  /*
  for(unsigned int i = 0; i < N; i++){
    std::cout << image_paths[i] << std::endl;
    if(i < N-1){
      for(auto p : points[i].first){
        std::cout << "[" << p(0) << ", " << p(1) << "] ";
      }
      std::cout << std::endl;
      for(auto p : points[i].second){
        std::cout << "[" << p(0) << ", " << p(1) << "] ";
      }
      std::cout << std::endl;
    }
  }
  */

  // Compute homographies
  std::cout << "Preparing Hs" << std::endl;
  std::vector<Eigen::Matrix3f> Hs;
  Eigen::Matrix3f H0 = Eigen::Matrix3f::Identity(3,3);
  Hs.push_back(H0);

  for(unsigned int i = center+1; i < N; i++){
    std::cout << "Computing H between " << i-1 << " and " << i << std::endl;
    auto Hdiff = find_homography(points[i-1].first, points[i-1].second);
    auto Habs = Hdiff * Hs.back();
    Hs.push_back(Habs);
  }
  for(int i = center-1; i > -1; i--){
    std::cout << "Computing H between " << i+1 << " and " << i << std::endl;
    auto Hdiff = find_homography(points[i].second, points[i].first);
    auto Habs = Hdiff * Hs.front();
    Hs.insert(Hs.begin(), Habs);
  }
  assert(Hs.size() == N);

  // Compute inverses
  std::vector<Eigen::Matrix3f> His;
  for(const auto& H : Hs)
    His.push_back(H.inverse());

  // Load images
  std::cout << "Loading images" << std::endl;
  std::vector<sga::Image> images;
  for(std::string image_path : image_paths){
    image_path = config_dir + "/" + image_path;

    int w,h,n;
    stbi_set_flip_vertically_on_load(1);
    unsigned char* data = stbi_load(image_path.c_str(), &w, &h, &n, 4);
    if(!data){
      std::cout << "Opening image '" << image_path << "' failed: " << stbi_failure_reason() << std::endl;
      return 1;
    }
    sga::Image image(w, h, 4, sga::ImageFormat::NInt8, sga::ImageFilterMode::Anisotropic);
    image.putData(std::vector<uint8_t>(data, data + w*h*4));
    free(data);

    images.push_back(image);
  }

  std::cout << "Preparing render resources" << std::endl;

  // Prepare image bounding boxes
  Eigen::ArrayXXf imgBBs(4*N,3);
  for(unsigned int i = 0; i < N; i++){
    auto& p = images[i];
    auto& Hi = His[i];
    Eigen::Vector3f v0(0,0,1);
    Eigen::Vector3f v1(0,p.getHeight(),1);
    Eigen::Vector3f v2(p.getWidth(),0,1);
    Eigen::Vector3f v3(p.getWidth(),p.getHeight(),1);
    imgBBs.block(4*i + 0, 0, 1, 3) = (Hi*v0).transpose();
    imgBBs.block(4*i + 1, 0, 1, 3) = (Hi*v1).transpose();
    imgBBs.block(4*i + 2, 0, 1, 3) = (Hi*v2).transpose();
    imgBBs.block(4*i + 3, 0, 1, 3) = (Hi*v3).transpose();
  }
  imgBBs.colwise() /= imgBBs.col(2);
  Eigen::Vector3f BBmax, BBmin;
  BBmax = imgBBs.colwise().maxCoeff();
  BBmin = imgBBs.colwise().minCoeff();
  Eigen::Vector3f BBsize = BBmax - BBmin;
  Eigen::Vector3f offset = BBmin;
  std::cout << "offset " << offset << std::endl;

  // Create target image
  sga::Image result(BBsize(0), BBsize(1));

  // Prepare a VBO
  struct VertData{
    Eigen::Vector2f pos;
  };
  std::vector<VertData> vertices = {
    {{0,0}},{{0,1}},{{1,0}},
    {{1,1}},{{1,0}},{{0,1}}
  };
  sga::VBO vbo({sga::DataType::Float2}, vertices.size());
  vbo.write(vertices);

  // Prepare shaders
  auto vertShader = sga::VertexShader::createFromSource(R"(
    mat3 align = mat3(vec3(2, 0, 0),vec3(0, 2, 0),vec3(-1, -1, 1));
    void main(){
      vec2 pos_texturespace = in_position * textureSize(image,0);
      vec3 pos_transformed_homog = H * vec3(pos_texturespace,1);
      float perspective_factor = 1/pos_transformed_homog.z;
      vec2 pos_transformed = pos_transformed_homog.xy/pos_transformed_homog.z;
      vec2 pos3 = 2*(pos_transformed - offset)/sgaResolution.xy - 1;
      gl_Position = vec4(pos3,0,1);
      imageUVW = vec3(in_position.x, 1 - in_position.y, 1) * perspective_factor;
    }
  )");
  vertShader.addInput(sga::DataType::Float2, "in_position");
  vertShader.addOutput(sga::DataType::Float3, "imageUVW");
  vertShader.addSampler("image");
  vertShader.addUniform(sga::DataType::Mat3, "H");
  vertShader.addUniform(sga::DataType::Float2, "offset");
  auto fragShader = sga::FragmentShader::createFromSource(R"(
    void main(){
      out_color = textureProj(image, imageUVW);
    }
  )");
  fragShader.addOutput(sga::DataType::Float4, "out_color");
  fragShader.addInput(sga::DataType::Float3, "imageUVW");
  fragShader.addSampler("image");
  auto program = sga::Program::createAndCompile(vertShader,fragShader);

  // Prepare pipeline
  sga::Pipeline pipeline;
  pipeline.setProgram(program);
  pipeline.setTarget({result});
  pipeline.setFaceCull(sga::FaceCullMode::None);
  pipeline.setBlendModeColor(sga::BlendFactor::One, sga::BlendFactor::OneMinusSrcAlpha);
  pipeline.setBlendModeAlpha(sga::BlendFactor::One, sga::BlendFactor::OneMinusSrcAlpha);
  pipeline.clear();

  std::cout << "Rendering" << std::endl;

  // Draw!
  pipeline.uniform["offset"] = Eigen::Vector2f{offset(0), offset(1)};
  for(unsigned int i = 0; i < N; i++){
    pipeline.sampler["image"] = images[i];
    pipeline.uniform["H"] = His[i];
    std::cout << His[i] << std::endl;
    pipeline.draw(vbo);
  }

  // Prepare another pipeline, just for rendering image edges
  if(render_lines){
    auto linesFragShader = sga::FragmentShader::createFromSource(R"(
      void main(){out_color = vec4(1,0,0,0.2);}
    )");
    linesFragShader.addOutput(sga::DataType::Float4, "out_color");
    linesFragShader.addInput(sga::DataType::Float3, "imageUVW");
    auto lines_program = sga::Program::createAndCompile(vertShader,linesFragShader);
    sga::Pipeline lines_pipeline;
    lines_pipeline.setPolygonMode(sga::PolygonMode::LineStrip);
    lines_pipeline.setLineWidth(2.0);
    lines_pipeline.setTarget(result);
    lines_pipeline.setProgram(lines_program);
    lines_pipeline.setBlendModeColor(sga::BlendFactor::One, sga::BlendFactor::OneMinusSrcAlpha);
    lines_pipeline.setBlendModeAlpha(sga::BlendFactor::One, sga::BlendFactor::OneMinusSrcAlpha);

    // VBO for lines
    std::vector<VertData> lines_vertices = {
      {{0,0}},{{0,1}},{{1,1}},{{1,0}},{{0,0}}
    };
    sga::VBO lines_vbo({sga::DataType::Float2}, lines_vertices.size());
    lines_vbo.write(lines_vertices);

    lines_pipeline.uniform["offset"] = Eigen::Vector2f{offset(0),offset(1)};
    for(unsigned int i = 0; i < N; i++){
      lines_pipeline.sampler["image"] = images[i];
      lines_pipeline.uniform["H"] = His[i];
      lines_pipeline.draw(lines_vbo);
    }
  }

  // Save result
  std::cout << "Saving result to " << output_path << std::endl;
  result.savePNG(output_path);

  renderdoc_capture_end();

  sga::terminate();
}

ext: cpp

max_stars_repo_name: rafalcieslak/libsga

max_issues_repo_name: rafalcieslak/libsga

max_forks_repo_name: rafalcieslak/libsga


text:
#pragma once

#include <Eigen/Dense>
#include <memory>

class Test;
class RobotSystem;

class EnvInterface {
   protected:
    Test* test_;
    RobotSystem* robot_;
    int count_;
    double running_time_;

   public:
    EnvInterface() {
        count_ = 0;
        running_time_ = 0.;
    }
    virtual ~EnvInterface(){};

    // Get Command through Test
    virtual void getCommand(void* _sensor_data, void* _command_data) = 0;
};


text:
/**
 * Copyright (c) 2012, Akamai Technologies
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 *   Redistributions in binary form must reproduce the above
 *   copyright notice, this list of conditions and the following
 *   disclaimer in the documentation and/or other materials provided
 *   with the distribution.
 *
 *   Neither the name of the Akamai Technologies nor the names of its
 *   contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef __TYPECHECKCONTEXT_HH__
#define __TYPECHECKCONTEXT_HH__

#include <map>
#include <stack>
#include <string>
#include <boost/dynamic_bitset.hpp>

class FieldType;
class IQLToLLVMLValue;
class RecordType;
class RecordMemberList;

class TypeCheckConfiguration
{
private:
  bool mCaseInsensitive;
public:
  TypeCheckConfiguration(bool caseInsensitive=false)
    :
    mCaseInsensitive(caseInsensitive)
  {
  }

  void caseInsensitive(bool val)
  {
    mCaseInsensitive = val;
  }

  bool caseInsensitive() const
  {
    return mCaseInsensitive;
  }

  // TODO: For the moment lets make this global.
  static TypeCheckConfiguration & get()
  {
    static TypeCheckConfiguration config;
    return config;
  }
};

class AliasedRecordType
{
private:
  std::string mAlias;
  const RecordType * mType;
public:
  // Compiler generated copy c'tor and assignment OK.
  AliasedRecordType(const std::string& alias, const RecordType * ty)
    :
    mAlias(alias),
    mType(ty)
  {
  }
  ~AliasedRecordType()
  {
  }
  const std::string& getAlias() const { return mAlias; }
  const RecordType * getType() const { return mType; }
};

class TreculSymbolTableEntry
{
private:
  const FieldType * mType;
  IQLToLLVMLValue * mValue;
public:
  TreculSymbolTableEntry();
  TreculSymbolTableEntry(const FieldType * ft);
  TreculSymbolTableEntry(IQLToLLVMLValue * val);
  TreculSymbolTableEntry(const FieldType * ft, IQLToLLVMLValue * val);
  ~TreculSymbolTableEntry();
  const FieldType * getType() const;
  IQLToLLVMLValue * getValue() const;
};

/**
 * The symbol table allows for two part names of variables with an optional
 * prefix.  If a variable name is unique without its prefix then it may be referenced
 * without it, otherwise there is an ambiguous reference.  In all cases it is
 * permissible to reference a field with its fully qualified name.
 */
class TreculSymbolTable
{
public:
  typedef std::map<std::string, TreculSymbolTableEntry *>::iterator table_iterator;
  typedef std::map<std::string, TreculSymbolTableEntry *>::const_iterator table_const_iterator;
private:
  // Lookup by two part name.
  std::map<std::string, TreculSymbolTableEntry *> mNameLookup;
  // Lookup by unprefixed name.
  std::map<std::string, TreculSymbolTableEntry *> mUnprefixedNameLookup;
  // Sentinel value for detecting ambiguous unprefixed names.
  TreculSymbolTableEntry mAmbiguous;
  // Is this symbol table case insensitive?
  bool mCaseInsensitive;

  std::string makeKey(const char * nm, const char * nm2) const;
public:
  TreculSymbolTable(const TypeCheckConfiguration & typeCheckConfig);
  ~TreculSymbolTable();
  void clear();
  TreculSymbolTableEntry * lookup(const char * nm, const char * nm2);
  void add(const char * nm, const char * nm2, const FieldType * ft);
  void add(const char * nm, const char * nm2, IQLToLLVMLValue * val);
  void add(const char * nm, const char * nm2,
	   const FieldType * ft, IQLToLLVMLValue * val);
  bool contains(const char * nm, const char * nm2) const;
};

class TypeCheckContext
{
private:
  std::map<std::string, const RecordType *> mInputRecords;
  TreculSymbolTable mSymbolTable;
  TreculSymbolTable mAggregateTable;
  std::stack<const FieldType *> mCaseType;
public:
  typedef RecordMemberList member_list;
  class DynamicRecordContext& mContext;
private:
  const RecordType * mOutputRecord;
  TreculSymbolTable * mTypeCheckSymbolTable;
  TreculSymbolTable * mAggregateTypeCheckSymbolTable;
  TreculSymbolTable * mSaveTypeCheckSymbolTable;
  member_list * mRecordMembers;

  // One member per aggregate function.
  member_list * mAggregateMembers;
  // A record where aggregate functions
  // can be calculated.
  const RecordType * mAggregateRecord;

  /**
   * Type check and create an INTERVAL type constructor.
   * N.B.  Note use of int32_t for the unit argument.
   * This is actually an IntervalType::IntervalUnit but I don't
   * want to include the header.
   * Someday we'll be able to forward declare the enum but right now
   * that functionality is bleeding edge  standard C++0x but not
   * implemented in most compilers.
   */
  const FieldType * internalBuildInterval(const FieldType * ty,
					  int32_t unit);

  bool isBuiltinFunction(const char * name);

  void init(const std::vector<AliasedRecordType>& sources,
	    const std::vector<boost::dynamic_bitset<> >& masks);

public:
  TypeCheckContext(const TypeCheckConfiguration & typeCheckConfig,
		   class DynamicRecordContext & recCtxt);

  /**
   * Initialize type check context with a list of
   * named Trecul record types (structs).
   * mask arguments indicate which fields of each input struct
   * to include in the environment.
   */
  TypeCheckContext(const TypeCheckConfiguration & typeCheckConfig,
		   DynamicRecordContext & recCtxt,
		   const std::vector<AliasedRecordType>& sources);

  TypeCheckContext(const TypeCheckConfiguration & typeCheckConfig,
		   DynamicRecordContext & recCtxt,
		   const std::vector<AliasedRecordType>& sources,
		   const std::vector<boost::dynamic_bitset<> >& masks);

  /**
   * Initialize type check of aggregate functions.
   * When type checking the parameters of an aggregate
   * function the entire record is available to the calculation
   * but when type checking the expressions outside the scope
   * of an aggregate function only the group by keys are available.
   */
  TypeCheckContext(const TypeCheckConfiguration & typeCheckConfig,
		   DynamicRecordContext & recCtxt,
		   const RecordType * input,
		   const std::vector<std::string>& groupKeys,
		   bool isOlap);

  ~TypeCheckContext();
  void loadBuiltinFunctions();

  /**
   * Retrieve the output of record construction.
   */
  const RecordType * getOutputRecord()
  {
    return mOutputRecord;
  }

  /**
   * Retrieve the record where aggregate functions
   * may be built.
   */
  const RecordType * getAggregateRecord();

  /**
   * Set value statement
   */
  void buildSetValue(const FieldType * lhs,
		     const FieldType * rhs);

  /**
   * Switch statements
   */
  void beginSwitch(const FieldType * e);

  /**
   * Variable rvalue expression.
   * Variable names have an optional two part form.
   * If there is only one part then the argument nm2 may be NULL.
   */
  const FieldType * buildVariableRef(const char * nm, const char * nm2);

  /**
   * Declare local variable.
   */
  void buildLocal(const char * nm, const FieldType * ft);

  /**
   * Array reference expression.
   */
  const FieldType * buildArray(const std::vector<const FieldType *>& e);
  const FieldType * buildArrayRef(const FieldType * arrayTy,
				  const FieldType * idx);

  /**
   * Function call
   */
  const FieldType * buildCall(const char * f, std::vector<const FieldType *> & args);

  /**
   * Hashing and sorting
   */
  const FieldType * buildHash(std::vector<const FieldType *> & ty);
  const FieldType * buildSortPrefix(std::vector<const FieldType *> & ty);

  /**
   * Unary operations.
   */
  const FieldType * buildNegate(const FieldType * ty);

  /**
   * Binary operations.
   */
  const FieldType * buildAdd(const FieldType * lhs,
			     const FieldType * rhs);
  const FieldType * buildSub(const FieldType * lhs,
			     const FieldType * rhs);
  const FieldType * buildMul(const FieldType * lhs,
			     const FieldType * rhs);
  const FieldType * buildDiv(const FieldType * lhs,
			     const FieldType * rhs);
  const FieldType * buildModulus(const FieldType * lhs,
				 const FieldType * rhs);
  const FieldType * buildConcat(const FieldType * lhs,
                                const FieldType * rhs);
  const FieldType * buildBitwise(const FieldType * lhs,
				 const FieldType * rhs);
  const FieldType * buildBitwise(const FieldType * lhs);

  /**
   * Logical operations
   */
  const FieldType * buildEquals(const FieldType * lhs,
				const FieldType * rhs);
  const FieldType * buildCompare(const FieldType * lhs,
				 const FieldType * rhs);
  const FieldType * buildLogicalAnd(const FieldType * lhs,
				    const FieldType * rhs);
  const FieldType * buildLogicalNot(const FieldType * lhs);
  const FieldType * buildLike(const FieldType * lhs,
			      const FieldType * rhs);

  /**
   * Cast/Conversion
   */
  const FieldType * buildCast(const FieldType * lhs,
			      const FieldType * target);

  /**
   * Primitive types.
   */
  const FieldType * buildInt8Type(bool nullable = false);
  const FieldType * buildInt16Type(bool nullable = false);
  const FieldType * buildInt32Type(bool nullable = false);
  const FieldType * buildInt64Type(bool nullable = false);
  const FieldType * buildFloatType(bool nullable = false);
  const FieldType * buildDoubleType(bool nullable = false);
  const FieldType * buildDecimalType(bool nullable = false);
  const FieldType * buildDateType(bool nullable = false);
  const FieldType * buildDatetimeType(bool nullable = false);
  const FieldType * buildVarcharType();
  const FieldType * buildVarcharType(bool nullable);
  const FieldType * buildCharType(const char * sz, bool nullable = false);
  const FieldType * buildBooleanType(bool nullable = false);
  const FieldType * buildIPv4Type(const char * addr, bool nullable = false);
  const FieldType * buildIPv4Type(bool nullable = false);
  const FieldType * buildCIDRv4Type(bool nullable = false);
  const FieldType * buildIPv6Type(const char * addr, bool nullable = false);
  const FieldType * buildIPv6Type(bool nullable = false);
  const FieldType * buildCIDRv6Type(bool nullable = false);
  const FieldType * buildNilType();
  const FieldType * buildType(const char * typeName, bool nullable);

  /**
   * Array types
   */
  const FieldType * buildArrayType(const char * sz, const FieldType * elt, bool nullable = false);
  const FieldType * buildFixedArrayType(int32_t sz, const FieldType * elt, bool nullable = false);
  const FieldType * buildVariableArrayType(const FieldType * elt, bool nullable = false);

  /**
   * Interval types.
   */
  const FieldType * buildIntervalDay(const FieldType * ty);
  const FieldType * buildIntervalHour(const FieldType * ty);
  const FieldType * buildIntervalMinute(const FieldType * ty);
  const FieldType * buildIntervalMonth(const FieldType * ty);
  const FieldType * buildIntervalSecond(const FieldType * ty);
  const FieldType * buildIntervalYear(const FieldType * ty);
  const FieldType * buildInterval(const char * intervalType, const FieldType * ty);

  /**
   * CASE expressions.
   */
  void beginCase();
  void addCondition(const FieldType * condVal);
  void addValue(const FieldType * thenVal);
  const FieldType * buildCase();

  /**
   * Ternary If/Then/Else
   */
  const FieldType * buildIfThenElse(const FieldType * condVal,
				    const FieldType * thenVal,
				    const FieldType * elseVal);

  /**
   * Record builder methods.
   */
  void beginRecord();
  void addField(const char * name, const FieldType * ty);
  void addFields(const char * recordName);
  void quotedId(const char * id, const char * format);
  void buildRecord();

  /**
   * Intrinsic functions
   */
  const FieldType * buildLeast(const std::vector<const FieldType *>& args);
  const FieldType * buildIsNull(const std::vector<const FieldType *>& args);

  /**
   * Aggregate function building.
   */
  void beginAggregateFunction();
  const FieldType * buildAggregateFunction(const FieldType * ty);

  /**
   * Automatic type promotion interface.
   */
  static const FieldType * castTo(const FieldType * lhs,
				  const FieldType * rhs);

  static const FieldType * leastCommonType(const FieldType * e1,
					   const FieldType * e2);

  static const FieldType * leastCommonTypeNullable(const FieldType * e1,
						   const FieldType * e2);

  // Lookup a symbol
  const FieldType * lookupType(const char * nm, const char * nm2);
};

#endif

ext: hh

max_stars_repo_name: lairofthegoldinblair/trecul

max_issues_repo_name: lairofthegoldinblair/trecul

max_forks_repo_name: lairofthegoldinblair/trecul


text:
#include <algorithm>
#include <fstream>
#include <numbers>

#include <boost/endian.hpp>

#include <range/v3/view.hpp>

#include <spdlog/spdlog.h>

#include <zlib.h>

#include <opencv2/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>

#include <osmpbf/fileformat.pb.h>
#include <osmpbf/osmformat.pb.h>

std::optional<std::uint32_t> value_for_key(auto &&element,
                                           const std::uint32_t &key) {
  for (decltype(element.keys().size()) i = 0; i < element.keys().size(); ++i) {
    if (element.keys(i) == key) {
      return element.vals(i);
    }
  }

  return std::nullopt;
}

bool has_key(auto &&element, const std::uint32_t &key) {
  return std::ranges::find(element.keys(), key) != element.keys().end();
}

bool has_attribute(auto &&element, const std::uint32_t &key,
                   const std::uint32_t &value) {
  const auto entries = ranges::views::zip(element.keys(), element.vals());
  return std::ranges::find(entries, std::make_pair(key, value)) !=
         entries.end();
}

bool has_attribute(auto &&keys, auto &&vals, const std::uint32_t &key,
                   const std::uint32_t &value) {
  const auto entries = ranges::views::zip(keys, vals);
  return std::ranges::find(entries, std::make_pair(key, value)) !=
         entries.end();
}

struct StringAttributeMap {
  StringAttributeMap(const OSMPBF::PrimitiveBlock &block) {
    for (int i = 0; i < block.stringtable().s_size(); ++i) {
      const auto &s = block.stringtable().s(i);
      if (s == "highway") {
        highway = i;
      } else if (s == "street_lamp") {
        street_lamp = i;
      } else if (s == "lit") {
        lit = i;
      } else if (s == "no") {
        no = i;
      } else if (s == "tower:type") {
        tower_type = i;
      } else if (s == "lighting") {
        lighting = i;
      }
    }
  }

  std::uint32_t highway = 0;
  std::uint32_t street_lamp = 0;
  std::uint32_t lit = 0;
  std::uint32_t no = 0;
  std::uint32_t tower_type = 0;
  std::uint32_t lighting = 0;
};

struct BoundingBox {
  static BoundingBox fromPoints(auto &&points) {
    BoundingBox result;

    for (const auto &point : points) {
      result.min.x = std::min(result.min.x, point.x);
      result.min.y = std::min(result.min.y, point.y);
      result.max.x = std::max(result.max.x, point.x);
      result.max.y = std::max(result.max.y, point.y);
    }

    return result;
  }

  auto ratio() const { return (max.x - min.x) / (max.y - min.y); }

  using numeric_limits = std::numeric_limits<cv::Point2d::value_type>;
  cv::Point2d min{numeric_limits::infinity(), numeric_limits::infinity()};
  cv::Point2d max{-numeric_limits::infinity(), -numeric_limits::infinity()};
};

struct Node {
  Node(double lon, double lat, bool is_street_lamp)
      : lon{lon}, lat{lat}, is_street_lamp{is_street_lamp} {
    using std::numbers::pi;
    using namespace std;
    const auto rad = [](const auto &deg) { return deg / 180.0 * pi; };

    x = 1.0 / (2 * pi) * 2 * (rad(lon) + pi);
    y = 1.0 / (2 * pi) * 2 * (pi - log(tan(pi / 4.0 + rad(lat) / 2.0)));
  }

  double lon;
  double lat;
  bool is_street_lamp;

  double x;
  double y;

  size_t refcount = 0;
};

using NodeRef = std::int64_t;

struct Road {
  std::vector<NodeRef> nodes;
  std::optional<bool> is_lit;
};

std::vector<char> zlib(const OSMPBF::Blob &blob) {
  decltype(zlib(blob)) result;

  if (!blob.has_zlib_data()) {
    return result;
  }

  result.resize(blob.raw_size());
  size_t uncompressedSize = result.size();
  if (uncompress(reinterpret_cast<Bytef *>(result.data()), &uncompressedSize,
                 reinterpret_cast<Bytef *>(
                     const_cast<char *>(blob.zlib_data().c_str())),
                 blob.zlib_data().size()) != Z_OK) {
    spdlog::critical("[zlib] uncompress failed.");
  }

  if (uncompressedSize != result.size()) {
    spdlog::critical(
        "[zlib] uncompressed size does not match expected one in header.");
  }

  return result;
}

size_t read_pbf_segment(std::ifstream &stream,
                        std::unordered_map<NodeRef, Node> &points,
                        std::vector<Road> &roads) {
  boost::endian::big_int32_t size;
  stream.read(reinterpret_cast<char *>(&size), sizeof(size));

  if (size == 0) {
    return 0;
  }

  std::vector<char> buffer(size);
  stream.read(buffer.data(), buffer.size());

  OSMPBF::BlobHeader blobheader;
  if (!blobheader.ParseFromArray(buffer.data(), buffer.size())) {
    spdlog::critical(
        "Failed to parse OSMPBF::BlobHeader (size is given as {} bytes).",
        size);
    return 0;
  }

  buffer.resize(blobheader.datasize());
  stream.read(buffer.data(), buffer.size());
  OSMPBF::Blob blob;
  if (!blob.ParseFromArray(buffer.data(), buffer.size())) {
    spdlog::critical(
        "Failed to parse OSMPBF::Blob (size is given as {} bytes).",
        blobheader.datasize());
    return 0;
  }

  if (!blob.has_zlib_data() || blob.has_lzma_data() || blob.has_raw()) {
    spdlog::critical(
        "[read_pbf_segment] Found a segment that is not zlib compressed. Only "
        "zlib compressed segments are supported.");
    return 0;
  }

  auto blockbuffer = zlib(blob);

  if (blobheader.type() == "OSMHeader") {

  } else if (blobheader.type() == "OSMData") {
    OSMPBF::PrimitiveBlock block;
    if (!block.ParseFromArray(blockbuffer.data(), blockbuffer.size())) {
      spdlog::critical("Failed to parse block");
    }

    const auto unpackLongitude = [&](const auto &packedLon) {
      return 0.000000001 *
             (block.lon_offset() + (block.granularity() * packedLon));
    };

    const auto unpackLatitude = [&](const auto &packedLat) {
      return 0.000000001 *
             (block.lat_offset() + (block.granularity() * packedLat));
    };

    const StringAttributeMap strings{block};

    for (const auto &group : block.primitivegroup()) {
      const auto is_street_lamp = [&](const auto &...args) {
        return has_attribute(args..., strings.highway, strings.street_lamp) ||
               has_attribute(args..., strings.tower_type, strings.lighting);
      };

      //
      // Nodes
      //
      std::transform(
          group.nodes().begin(), group.nodes().end(),
          std::inserter(points, points.begin()),
          [&](const auto &node) -> std::decay_t<decltype(points)>::value_type {
            return {std::piecewise_construct, std::forward_as_tuple(node.id()),
                    std::forward_as_tuple(unpackLongitude(node.lon()),
                                          unpackLatitude(node.lat()),
                                          is_street_lamp(node))};
          });

      //
      // DenseNodes
      //
      if (group.has_dense()) {
        const auto &dense = group.dense();

        std::int64_t id = 0;
        std::int64_t packedLat = 0;
        std::int64_t packedLon = 0;

        using namespace ranges::views;
        for (const auto &[delta_id, delta_lat, delta_lon, attr] :
             zip(dense.id(), dense.lat(), dense.lon(),
                 dense.keys_vals() | split(0))) {
          id += delta_id;
          packedLat += delta_lat;
          packedLon += delta_lon;

          const auto keys = attr | stride(2);
          const auto vals = attr | tail | stride(2);
          points.emplace(std::piecewise_construct, std::forward_as_tuple(id),
                         std::forward_as_tuple(unpackLongitude(packedLon),
                                               unpackLatitude(packedLat),
                                               is_street_lamp(keys, vals)));
        }
      }

      //
      // Ways
      //
      const auto is_highway = [&](const auto &way) {
        return has_key(way, strings.highway);
      };

      std::ranges::transform(group.ways() | std::views::filter(is_highway),
                             std::back_inserter(roads), [&](const auto &road) {
                               std::decay_t<decltype(roads)>::value_type result;

                               if (const auto lit_attr =
                                       value_for_key(road, strings.lit)) {
                                 result.is_lit = *lit_attr != strings.no;
                               }

                               std::int64_t node = 0;
                               result.nodes.reserve(road.refs().size());
                               for (const auto &delta_ref : road.refs()) {
                                 node += delta_ref;
                                 result.nodes.emplace_back(node);
                                 ++points.at(node).refcount;
                               }

                               return result;
                             });
    }
  }

  return blob.raw_size();
}

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

  if (argc != 3) {
    spdlog::critical("Usage: {} pbf-file out-image-file", argv[0]);
    return -1;
  }

  const auto inputFile = argv[1];
  const auto outputFile = argv[2];

  //
  // Parse OSM export
  //

  std::ifstream file{inputFile, std::ios::binary};
  if (!file.is_open()) {
    spdlog::critical("Failed to open PBF file \"{}\".", inputFile);
    return -2;
  }

  std::unordered_map<NodeRef, Node> nodes;
  std::vector<Road> roads;

  spdlog::info("Start parsing of PBF file.");

  size_t raw_size = 0;
  while (!file.eof()) {
    raw_size += read_pbf_segment(file, nodes, roads);
  }

  spdlog::info("Parsed {} bytes of data containing {} nodes and {} ways (with "
               "highway attribute).",
               raw_size, nodes.size(), roads.size());

  //
  // Define canvas
  //
  const auto bb = BoundingBox::fromPoints(
      nodes | std::views::values | std::views::filter([](const auto &point) {
        return point.refcount > 0 || point.is_street_lamp;
      }));
  cv::Mat image = cv::Mat::zeros(1024 * 5 / bb.ratio(), 1024 * 5, CV_8UC3);

  const auto imagePostion = [&](const auto &point) -> cv::Point2d {
    const auto x = [&](const auto &p) {
      return (p.x - bb.min.x) / (bb.max.x - bb.min.x) * image.cols;
    };

    const auto y = [&](const auto &p) {
      return (p.y - bb.min.y) / (bb.max.y - bb.min.y) * image.rows;
    };

    return {x(point), y(point)};
  };

  //
  // Draw Roads
  //
  size_t numLitRoads = 0;
  size_t numNonLitRoads = 0;
  size_t numRoadsWithoutLitTag = 0;

  for (const auto &road : roads) {
    const auto color = [&]() -> cv::Scalar {
      if (road.is_lit.has_value()) {
        if (road.is_lit.value()) {
          ++numLitRoads;
          return {0, 190, 190};
        } else {
          ++numNonLitRoads;
          return {0, 0, 63};
        }
      } else {
        ++numRoadsWithoutLitTag;
        return {63, 0, 0};
      }
    }();

    for (const auto &[startIndex, endIndex] :
         ranges::views::zip(road.nodes | ranges::views::drop_last(1),
                            road.nodes | ranges::views::drop(1))) {
      const auto &start = nodes.at(startIndex);
      const auto &end = nodes.at(endIndex);
      cv::line(image, imagePostion(start), imagePostion(end), color);
    }
  }
  spdlog::info("Lit: Yes={}, No={}, Unknown={}.", numLitRoads, numNonLitRoads,
               numRoadsWithoutLitTag);

  //
  // Draw Street Lamps
  //
  size_t numStreetLamps = 0;
  for (const auto &lamp :
       nodes | std::views::values | std::views::filter([](const auto &point) {
         return point.is_street_lamp;
       })) {
    cv::circle(image, imagePostion(lamp), 2, {0, 255, 255}, cv::FILLED);
    ++numStreetLamps;
  }
  spdlog::info("Found {} street lamps.", numStreetLamps);

  if (!cv::imwrite(outputFile, image)) {
    spdlog::critical("Failed to write output to \"{}\".", outputFile);
    return -3;
  }

  return 0;
}


text:
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include <vespa/storage/bucketdb/judyarray.h>
#include <boost/random.hpp>
#include <vespa/vespalib/gtest/gtest.h>
#include <gmock/gmock.h>
#include <map>
#include <vector>

using namespace ::testing;

namespace storage {

namespace {
    std::vector<std::pair<JudyArray::key_type, JudyArray::data_type>>
    getJudyArrayContents(const JudyArray& array) {
        std::vector<std::pair<JudyArray::key_type, JudyArray::data_type>> vals;
        for (JudyArray::const_iterator it = array.begin();
             it != array.end(); ++it)
        {
            vals.push_back(std::make_pair(it.key(), it.value()));
        }
        return vals;
    }
}

TEST(JudyArrayTest, iterating) {
    JudyArray array;
    // Test that things are sane for empty document
    ASSERT_EQ(array.begin(), array.end());
    // Add some values
    std::vector<std::pair<JudyArray::key_type, JudyArray::data_type>> values({
        {3, 2}, {5, 12}, {15, 8}, {13, 10}, {7, 6}, {9, 4}
    });
    for (uint32_t i=0; i<values.size(); ++i) {
        array.insert(values[i].first, values[i].second);
    }
    // Create expected result
    std::sort(values.begin(), values.end());
    // Test that we can iterate through const iterator
    auto foundVals = getJudyArrayContents(array);
    ASSERT_EQ(values, foundVals);

    {   // Test that we can alter through non-const iterator
        JudyArray::iterator it = array.begin();
        ++it;
        ++it;
        it.setValue(20);
        ASSERT_EQ((JudyArray::key_type) 7, it.key());
        ASSERT_EQ((JudyArray::data_type) 20, array[7]);
        it.remove();
        ASSERT_EQ((JudyArray::size_type) 5, getJudyArrayContents(array).size());
        ASSERT_EQ(array.end(), array.find(7));
        values.erase(values.begin() + 2);
        ASSERT_EQ(values, getJudyArrayContents(array));
        // And that we can continue iterating after removing.
        ++it;
        ASSERT_EQ((JudyArray::key_type) 9, it.key());
        ASSERT_EQ((JudyArray::data_type) 4, array[9]);
    }
    {   // Test printing of iterators
        JudyArray::ConstIterator cit = array.begin();
        EXPECT_THAT(cit.toString(), MatchesRegex("^ConstIterator\\(Key: 3, Valp: 0x[0-9a-f]{1,16}, Val: 2\\)$"));
        JudyArray::Iterator it = array.end();
        EXPECT_THAT(it.toString(), MatchesRegex("^Iterator\\(Key: 0, Valp: (0x)?0\\)$"));
    }
}

TEST(JudyArrayTest, dual_array_functions) {
    JudyArray array1;
    JudyArray array2;
    // Add values to array1
    std::vector<std::pair<JudyArray::key_type, JudyArray::data_type>> values1({
        {3, 2}, {5, 12}, {15, 8}, {13, 10}, {7, 6}, {9, 4}
    });
    for (uint32_t i=0; i<values1.size(); ++i) {
        array1.insert(values1[i].first, values1[i].second);
    }
    // Add values to array2
    std::vector<std::pair<JudyArray::key_type, JudyArray::data_type>> values2({
        {4, 5}, {9, 40}
    });
    for (uint32_t i=0; i<values2.size(); ++i) {
        array2.insert(values2[i].first, values2[i].second);
    }
    // Create expected result
    std::sort(values1.begin(), values1.end());
    std::sort(values2.begin(), values2.end());

    EXPECT_EQ(values1, getJudyArrayContents(array1));
    EXPECT_EQ(values2, getJudyArrayContents(array2));
    EXPECT_LT(array2, array1);
    EXPECT_NE(array1, array2);
    array1.swap(array2);
    EXPECT_EQ(values1, getJudyArrayContents(array2));
    EXPECT_EQ(values2, getJudyArrayContents(array1));
    EXPECT_LT(array1, array2);
    EXPECT_NE(array1, array2);

    // Test some operators
    JudyArray array3;
    for (uint32_t i=0; i<values1.size(); ++i) {
        array3.insert(values1[i].first, values1[i].second);
    }
    EXPECT_NE(array1, array3);
    EXPECT_EQ(array2, array3);
    EXPECT_FALSE(array2 < array3);
}

TEST(JudyArrayTest, size) {
    JudyArray array;
    EXPECT_EQ(array.begin(), array.end());
    EXPECT_TRUE(array.empty());
    EXPECT_EQ((JudyArray::size_type) 0, array.size());
    EXPECT_EQ((JudyArray::size_type) 0, array.getMemoryUsage());

    // Test each method one can insert stuff into array
    array.insert(4, 3);
    EXPECT_EQ(getJudyArrayContents(array).size(), array.size());
    array.insert(4, 7);
    EXPECT_EQ(getJudyArrayContents(array).size(), array.size());
    EXPECT_EQ((JudyArray::size_type) 24, array.getMemoryUsage());

    array[6] = 8;
    EXPECT_EQ(getJudyArrayContents(array).size(), array.size());
    array[6] = 10;
    EXPECT_EQ(getJudyArrayContents(array).size(), array.size());
    EXPECT_EQ((JudyArray::size_type) 40, array.getMemoryUsage());

    bool preExisted;
    array.find(8, true, preExisted);
    EXPECT_EQ(false, preExisted);
    EXPECT_EQ(getJudyArrayContents(array).size(), array.size());
    array.find(8, true, preExisted);
    EXPECT_EQ(true, preExisted);
    EXPECT_EQ(getJudyArrayContents(array).size(), array.size());
    EXPECT_EQ((JudyArray::size_type) 3, array.size());
    EXPECT_EQ((JudyArray::size_type) 56, array.getMemoryUsage());

    // Test each method one can remove stuff in array with
    array.erase(8);
    EXPECT_EQ(getJudyArrayContents(array).size(), array.size());
    array.erase(8);
    EXPECT_EQ(getJudyArrayContents(array).size(), array.size());
    EXPECT_EQ((JudyArray::size_type) 2, array.size());
    EXPECT_EQ((JudyArray::size_type) 40, array.getMemoryUsage());
}

TEST(JudyArrayTest, stress) {
    // Do a lot of random stuff to both judy array and std::map. Ensure equal
    // behaviour

    JudyArray judyArray;
    typedef std::map<JudyArray::key_type, JudyArray::data_type> StdMap;
    StdMap stdMap;

    boost::rand48 rnd(55);

    for (uint32_t checkpoint=0; checkpoint<50; ++checkpoint) {
        for (uint32_t opnr=0; opnr<500; ++opnr) {
            int optype = rnd() % 100;
            if (optype < 30) { // Insert
                JudyArray::key_type key(rnd() % 500);
                JudyArray::key_type value(rnd());
                judyArray.insert(key, value);
                stdMap[key] = value;
            } else if (optype < 50) { // operator[]
                JudyArray::key_type key(rnd() % 500);
                JudyArray::key_type value(rnd());
                judyArray[key] = value;
                stdMap[key] = value;
            } else if (optype < 70) { // erase()
                JudyArray::key_type key(rnd() % 500);
                EXPECT_EQ(stdMap.erase(key), judyArray.erase(key));
            } else if (optype < 75) { // size()
                EXPECT_EQ(stdMap.size(), judyArray.size());
            } else if (optype < 78) { // empty()
                EXPECT_EQ(stdMap.empty(), judyArray.empty());
            } else { // find()
                JudyArray::key_type key(rnd() % 500);
                auto it = judyArray.find(key);
                auto it2 = stdMap.find(key);
                EXPECT_EQ(it2 == stdMap.end(), it == judyArray.end());
                if (it != judyArray.end()) {
                    EXPECT_EQ(it.key(), it2->first);
                    EXPECT_EQ(it.value(), it2->second);
                }
            }
        }
        // Ensure judy array contents is equal to std::map's at this point
        StdMap tmpMap;
        for (JudyArray::const_iterator it = judyArray.begin();
             it != judyArray.end(); ++it)
        {
            tmpMap[it.key()] = it.value();
        }
        EXPECT_EQ(stdMap, tmpMap);
    }
}

} // storage

max_stars_repo_name: amahussein/vespa

max_issues_repo_name: amahussein/vespa

max_forks_repo_name: amahussein/vespa


text:
//==================================================================================================
/*!
  @file

  @copyright 2016 NumScale SAS

  Distributed under the Boost Software License, Version 1.0.
  (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/
//==================================================================================================
#ifndef BOOST_SIMD_ARCH_COMMON_GENERIC_FUNCTION_AUTOSPLAT_HPP_INCLUDED
#define BOOST_SIMD_ARCH_COMMON_GENERIC_FUNCTION_AUTOSPLAT_HPP_INCLUDED

#include <boost/dispatch/function/overload.hpp>
#include <boost/dispatch/hierarchy/functions.hpp>
#include <boost/simd/meta/hierarchy/simd.hpp>
#include <boost/simd/arch/common/tags.hpp>
#include <boost/config.hpp>

namespace boost { namespace simd { namespace ext
{
  namespace bs = boost::simd;
  namespace bd = boost::dispatch;

  // ({P,S},{S,P})
  // -----------------------------------------------------------------------------------------------

  BOOST_DISPATCH_OVERLOAD_FALLBACK ( (typename F, typename P0, typename S0, typename E0)
                                   , bd::elementwise_<F>
                                   , bd::cpu_
                                   , bd::scalar_<bd::unspecified_<S0>>
                                   , bs::pack_<bd::unspecified_<P0>, E0>
                                   )
  {
    using functor = bd::functor<F>;
    using value_t = typename P0::value_type;

    auto operator()( S0 const& s0, P0 const& p0) const
    BOOST_NOEXCEPT_DECLTYPE_BODY(functor()(P0(value_t(s0)), p0))
  };

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

  BOOST_DISPATCH_OVERLOAD_FALLBACK ( (typename F, typename P0, typename S0, typename E0)
                                   , bd::elementwise_<F>
                                   , bd::cpu_
                                   , bs::pack_<bd::unspecified_<P0>, E0>
                                   , bd::scalar_<bd::unspecified_<S0>>
                                   )
  {
    using functor = bd::functor<F>;
    using value_t = typename P0::value_type;

    auto operator()( P0 const& p0
                   , S0 const& s0
                   ) const
    BOOST_NOEXCEPT_DECLTYPE_BODY(functor()(p0, P0(value_t(s0)) ) )
  };

  // ({P,S},{P,S},{P,S})
  // -----------------------------------------------------------------------------------------------

  BOOST_DISPATCH_OVERLOAD_FALLBACK ( ( typename F
                                     , typename P0
                                     , typename S0
                                     , typename E0
                                     )
                                   , bd::elementwise_<F>
                                   , bd::cpu_
                                   , bs::pack_<bd::unspecified_<P0>, E0>
                                   , bs::pack_<bd::unspecified_<P0>, E0>
                                   , bd::scalar_<bd::unspecified_<S0>>
                                   )
  {
    using functor = bd::functor<F>;
    using value_t = typename P0::value_type;

    auto operator()( P0 const& p0
                   , P0 const& p1
                   , S0 const& s0
                   ) const
    BOOST_NOEXCEPT_DECLTYPE_BODY(functor()(p0, p1, P0(value_t(s0))))
  };

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

  BOOST_DISPATCH_OVERLOAD_FALLBACK ( ( typename F
                                     , typename P0
                                     , typename S0
                                     , typename E0
                                     )
                                   , bd::elementwise_<F>
                                   , bd::cpu_
                                   , bs::pack_<bd::unspecified_<P0>, E0>
                                   , bd::scalar_<bd::unspecified_<S0>>
                                   , bs::pack_<bd::unspecified_<P0>, E0>
                                   )
  {
    using functor = bd::functor<F>;
    using value_t = typename P0::value_type;

    auto operator()( P0 const& p0
                   , S0 const& s0
                   , P0 const& p1
                   ) const
    BOOST_NOEXCEPT_DECLTYPE_BODY(functor()(p0, P0(value_t(s0)), p1))
  };

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

  BOOST_DISPATCH_OVERLOAD_FALLBACK ( ( typename F
                                     , typename P0
                                     , typename S0
                                     , typename E0
                                     )
                                   , bd::elementwise_<F>
                                   , bd::cpu_
                                   , bd::scalar_<bd::unspecified_<S0>>
                                   , bs::pack_<bd::unspecified_<P0>, E0>
                                   , bs::pack_<bd::unspecified_<P0>, E0>
                                   )
  {
    using functor = bd::functor<F>;
    using value_t = typename P0::value_type;

    auto operator()( S0 const& s0
                   , P0 const& p0
                   , P0 const& p1
                   ) const
    BOOST_NOEXCEPT_DECLTYPE_BODY(functor()(P0(value_t(s0)), p0, p1))
  };

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

  BOOST_DISPATCH_OVERLOAD_FALLBACK ( ( typename F
                                     , typename P0
                                     , typename S0
                                     , typename S1
                                     , typename E0
                                     )
                                   , bd::elementwise_<F>
                                   , bd::cpu_
                                   , bd::scalar_<bd::unspecified_<S0>>
                                   , bd::scalar_<bd::unspecified_<S1>>
                                   , bs::pack_<bd::unspecified_<P0>, E0>
                                   )
  {
    using functor = bd::functor<F>;
    using value_t = typename P0::value_type;

    auto operator()( S0 const& s0
                   , S1 const& s1
                   , P0 const& p0
                   ) const
    BOOST_NOEXCEPT_DECLTYPE_BODY(functor()(P0(value_t(s0)), P0(value_t(s1)), p0))
  };

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

  BOOST_DISPATCH_OVERLOAD_FALLBACK ( ( typename F
                                     , typename P0
                                     , typename S0
                                     , typename S1
                                     , typename E0
                                     )
                                   , bd::elementwise_<F>
                                   , bd::cpu_
                                   , bd::scalar_<bd::unspecified_<S0>>
                                   , bs::pack_<bd::unspecified_<P0>, E0>
                                   , bd::scalar_<bd::unspecified_<S1>>
                                   )
  {
    using functor = bd::functor<F>;
    using value_t = typename P0::value_type;

    auto operator()( S0 const& s0
                   , P0 const& p0
                   , S1 const& s1
                   ) const
    BOOST_NOEXCEPT_DECLTYPE_BODY(functor()(P0(value_t(s0)), p0, P0(value_t(s1))))
  };

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

  BOOST_DISPATCH_OVERLOAD_FALLBACK ( ( typename F
                                     , typename P0
                                     , typename S0
                                     , typename S1
                                     , typename E0
                                     )
                                   , bd::elementwise_<F>
                                   , bd::cpu_
                                   , bs::pack_<bd::unspecified_<P0>, E0>
                                   , bd::scalar_<bd::unspecified_<S0>>
                                   , bd::scalar_<bd::unspecified_<S1>>
                                   )
  {
    using functor = bd::functor<F>;
    using value_t = typename P0::value_type;

    auto operator()( P0 const& p0
                   , S0 const& s0
                   , S1 const& s1
                   ) const
    BOOST_NOEXCEPT_DECLTYPE_BODY(functor()(p0, P0(value_t(s0)), P0(value_t(s1))))
  };

} } }

#endif


text:
#pragma once
//
// Copyright (c) 2015, J2 Innovations
// Copyright (c) 2012 Brian Frank
// Licensed under the Academic Free License version 3.0
// History:
//   26 Aug 2014  Radu Racariu<radur@2inn.com> Ported to C++
//   06 Jun 2011  Brian Frank  Creation
//

#include "val.hpp"
#include <boost/ptr_container/ptr_map.hpp>

namespace haystack {

    class Ref;
    /**
     Dict is a map of name/Val pairs

     @see Project Haystack
     */
    class Dict : boost::noncopyable
    {
    public:
        typedef std::auto_ptr<Dict> auto_ptr_t;
        // dict internal type
        typedef boost::ptr_map < std::string, haystack::Val > dict_t;
        typedef dict_t::const_iterator const_iterator;

        Dict() {};
        virtual ~Dict(){}

        /**
        Singleton for empty set of tags.
        */
        static const Dict& EMPTY;

        /**
        Return true if size is zero
        */
        virtual const bool is_empty() const;
        /**
        Return number of tag name / value pairs
        */
        virtual const size_t size() const;
        /**
        Return if the given tag is present
        */
        virtual const bool has(const std::string& name) const;

        /**
        Return if the given tag is not present
        */
        virtual const bool missing(const std::string& name) const;

        /**
        Get the "id" tag as Ref
        */
        const Ref& id() const;

        /**
        Get a tag by name
        */
        virtual const Val& get(const std::string& name, bool checked = true) const;

        /**
        Iteratator to walk each name / tag pair
        */
        const_iterator begin() const;
        const_iterator end() const;

        /**
        String format is for human consumption only
        */
        const std::string to_string() const
        {
            return to_zinc();
        }

        /**
        Encode values to zinc format
        */
        const std::string to_zinc() const;

        /**
        Get display string for this entity:
        - dis tag
        - id tag
        */
        const std::string dis() const;

        //////////////////////////////////////////////////////////////////////////
        // Get Conveniences
        //////////////////////////////////////////////////////////////////////////

        /**
        Get tag as Bool or raise runtime_exception.
        */
        bool get_bool(const std::string& name) const;

        /**
        Get tag as Str or raise runtime_exception.
        */
        const std::string& get_str(const std::string& name) const;

        /**
        Get tag as Ref or raise runtime_exception.
        */
        const Ref& get_ref(const std::string& name) const;

        /**
        Get tag as Num or raise runtime_exception.
        */
        long long get_int(const std::string& name) const;

        /**
        Get tag as Num or raise runtime_exception.
        */
        double get_double(const std::string& name) const;

        /**
        Returns a dict with the value added, Val is owned by this dict
        */
        Dict& add(std::string name, Val::auto_ptr_t val);

        /**
        Returns a dict with the value added, Val* is owned by this dict
        */
        Dict& add(std::string name, const Val* val);

        /**
        Returns a dict with the value added, Val& is cloned
        */
        Dict& add(std::string name, const Val& val);

        /**
        Returns a dict with the Marker added
        */
        Dict& add(std::string name);

        /**
        Returns a dict with the Str added
        */
        Dict& add(std::string name, const std::string& val);

        /**
        Returns a dict with the Num added
        */
        Dict& add(std::string name, double val, const std::string &unit = "");

        /**
        Returns a dict with the Dict added
        */
        Dict& add(const Dict& other);

        /**
        Clones this Dict and its values
        */
        virtual auto_ptr_t clone();

        /**
        Return if the given string is a legal tag name.  The
        first char must be ASCII lower case letter.  Rest of
        chars must be ASCII letter, digit, or underbar.
        */
        static const bool is_tag_name(const std::string &);

        /**
        Equality
        */
        virtual bool operator == (const Dict &b) const;
        bool operator != (const Dict &b) const;

        // Members
    private:
        dict_t m_map;
    };
};

max_stars_repo_name: kushaldalsania/haystack-cpp

max_issues_repo_name: kushaldalsania/haystack-cpp

max_forks_repo_name: kushaldalsania/haystack-cpp


text:
#include <algorithm>
#include <boost/range/irange.hpp>
#include <cmath>
#include <map>
#include <memory>
#include <set>

#include "bounding_edge.hpp"
#include "kd_tree_node.hpp"
#include "rtc_log.hpp"
#include "scoped_timer.hpp"

namespace rtc
{
kd_tree::kd_tree(const rtc::scene_model& ss) : bbox{ss.points}
{
  SCOPE_TIME_COUNTER;
  const auto& p = ss.points;
  const auto& t = ss.triangles;
  const std::uint32_t max_depth = 1.3F * std::log2(t.size()) + 8;

  auto make_bbox = [](auto& p, auto& tr) noexcept {
    return rtc::bounding_box{p[tr.vertex_a()], p[tr.vertex_b()], p[tr.vertex_c()]};
  };

  rtc::bounding_box node_bbox{p};
  std::vector<std::uint32_t> v(t.size());
  std::vector<bounding_box> primitive_bboxes;
  edge_buffer_array_t edge_buffer{
      edge_buffer_t(2 * t.size()), edge_buffer_t(2 * t.size()), edge_buffer_t(2 * t.size())};

  primitive_bboxes.reserve(t.size());

  std::for_each(t.begin(), t.end(), [&](auto& t) { primitive_bboxes.push_back(make_bbox(p, t)); });
  std::generate(v.begin(), v.end(), [i = 0]() mutable { return i++; });

  build_tree(root, node_bbox, std::move(v), primitive_bboxes, edge_buffer, max_depth);
}

auto kd_tree::cbegin(const rtc::math_ray& ray) const noexcept -> kd_tree::const_iterator
{
  if (auto range = bbox.intersection_values_for(ray))
  {
    const auto [tmin, tmax] = range.value();
    return const_iterator{ray, {root.get(), tmin, tmax}};
  }

  return const_iterator{};
}

auto kd_tree::cend(const rtc::math_ray&) const noexcept -> kd_tree::const_iterator { return const_iterator{}; }

kd_tree::~kd_tree() = default;
kd_tree::kd_tree(kd_tree&&) noexcept = default;
auto kd_tree::operator=(kd_tree&&) noexcept -> kd_tree& = default;

auto kd_tree::compute_node_split_paramters(edge_buffer_array_t& edge_buffer,
                                           const std::vector<std::uint32_t>& tr,
                                           const rtc::bounding_box& node_bbox,
                                           const std::vector<rtc::bounding_box>& primitive_bboxes)
{
  constexpr int isect_cost{80};
  constexpr int traversal_cost{1};
  constexpr rtc_float empty_bonus{0.5F};
  const auto node_diagonal{node_bbox.diagonal()};
  const rtc_float invTotalSA{1.0F / node_bbox.surface_area()};
  const rtc_float old_cost{isect_cost * static_cast<rtc_float>(tr.size())};

  int retries{0};
  int best_axis{-1};
  int best_offset{-1};
  rtc::axis axis{node_bbox.maximum_extent()};
  rtc_float best_cost{std::numeric_limits<rtc_float>::max()};

  do
  {
    const rtc::axis axis2{next(axis)}, axis3{next(axis2)};
    int below{}, above(tr.size());

    for (const auto i : boost::irange<std::size_t>(0, tr.size()))
    {
      const rtc::bounding_box& box{primitive_bboxes[tr[i]]};
      edge_buffer[int(axis)][2 * i] = {box.min_boundary().axis(axis), tr[i], bounding_edge_point::start};
      edge_buffer[int(axis)][2 * i + 1] = {box.max_boundary().axis(axis), tr[i], bounding_edge_point::end};
    }

    std::sort(&edge_buffer[int(axis)][0], &edge_buffer[int(axis)][0] + 2 * tr.size());

    for (const auto i : boost::irange<std::size_t>(0, 2 * tr.size()))
    {
      const rtc::bounding_edge_point& bp{edge_buffer[int(axis)][i]};
      const auto edge_t = bp.value;

      if (bp.type == bounding_edge_point::end)
        --above;
      if (bp.type == bounding_edge_point::start)
        ++below;

      if (edge_t > node_bbox.min_boundary().axis(axis) && edge_t < node_bbox.max_boundary().axis(axis))
      {
        const rtc_float belowSA{2 * (node_diagonal.axis(axis2) * node_diagonal.axis(axis3) +
                                     (edge_t - node_bbox.min_boundary().axis(axis)) *
                                         (node_diagonal.axis(axis2) + node_diagonal.axis(axis3)))};

        const rtc_float aboveSA{2 * (node_diagonal.axis(axis2) * node_diagonal.axis(axis3) +
                                     (node_bbox.max_boundary().axis(axis) - edge_t) *
                                         (node_diagonal.axis(axis2) + node_diagonal.axis(axis3)))};

        const rtc_float pBelow{belowSA * invTotalSA};
        const rtc_float pAbove{aboveSA * invTotalSA};
        const rtc_float eb{(above == 0 || below == 0) ? empty_bonus : 0};
        const rtc_float cost{traversal_cost + isect_cost * (1 - eb) * (pBelow * below + pAbove * above)};

        if (cost < best_cost)
        {
          best_cost = cost;
          best_axis = int(axis);
          best_offset = i;
        }
      }
    }
  } while ((best_axis == -1) && ((axis = next(axis), retries++) < 2));

  return std::make_tuple(best_axis, best_offset, best_cost, old_cost);
}

auto kd_tree::split_triangles(std::vector<std::uint32_t>&& tr_init,
                              const edge_buffer_array_t& edge_buffer,
                              const std::uint32_t best_axis,
                              const std::uint32_t best_offset)
{
  std::vector<std::uint32_t> tr{std::move(tr_init)}, left_set{}, right_set{};

  left_set.reserve(best_offset);
  right_set.reserve(2 * tr.size() - best_offset);

  for (auto i = 0; i < best_offset; ++i)
  {
    if (edge_buffer[best_axis][i].type == bounding_edge_point::start)
    {
      left_set.emplace_back(edge_buffer[best_axis][i].tr_index);
    }
  }

  for (auto i = best_offset + 1; i < 2 * tr.size(); ++i)
  {
    if (edge_buffer[best_axis][i].type == bounding_edge_point::end)
    {
      right_set.emplace_back(edge_buffer[best_axis][i].tr_index);
    }
  }
  return std::make_tuple(std::move(left_set), std::move(right_set));
}

void kd_tree::build_tree(std::unique_ptr<tree_node>& node,
                         rtc::bounding_box node_bbox,
                         std::vector<std::uint32_t> tr,
                         const std::vector<rtc::bounding_box>& primitive_bboxes,
                         edge_buffer_array_t& edge_buffer,
                         const std::uint32_t depth,
                         std::uint32_t bad_refines)
{
  const auto create_leaf_node = [&node, &tr] {
    node = std::make_unique<tree_node>();
    node->triangles = std::make_unique<kd_tree::value_type>();
    node->triangles->insert(node->triangles->end(), tr.begin(), tr.end());
  };

  if (tr.size() <= 1 || !depth)
    return create_leaf_node();

  const auto [axis, offset, cost, old_cost] =
      compute_node_split_paramters(edge_buffer, tr, node_bbox, primitive_bboxes);

  bad_refines += (cost > old_cost) ? 1 : 0;

  auto no_use_of_spliting_node = [old_cost = old_cost, cost = cost, axis = axis, &bad_refines, &tr] {
    return ((cost > 4 * old_cost) && (tr.size() < 16)) || (axis == -1) || (bad_refines == 3);
  };

  if (no_use_of_spliting_node())
    return create_leaf_node();

  auto [left_set, right_set] = split_triangles(std::move(tr), edge_buffer, axis, offset);
  bounding_box left_bbox{node_bbox}, right_bbox{node_bbox};

  node = std::make_unique<tree_node>();
  node->axis = {edge_buffer[axis][offset].value, static_cast<rtc::axis>(axis)};

  left_bbox.max_boundary().axis(node->axis.split) = right_bbox.min_boundary().axis(node->axis.split) = node->axis.value;

  build_tree(node->left, left_bbox, std::move(left_set), primitive_bboxes, edge_buffer, depth - 1, bad_refines);
  build_tree(node->right, right_bbox, std::move(right_set), primitive_bboxes, edge_buffer, depth - 1, bad_refines);
}

}  // namespace rtc

max_stars_repo_name: Abergard/rtc

max_issues_repo_name: Abergard/rtc

max_forks_repo_name: Abergard/rtc


text:
/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2014 Boone "Bea" Adkins
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
/**
 * @file
 *
 *
 *
 * @date Aug 22, 2013
 * @author Bea Adkins
 */

#include <boost/units/detail/utility.hpp>
#include <sstream>
#include <XmlRpcValue.h>

#include "assert_rng.h"
#include "belief_feature_value.h"
#include "feature_value.h"
#include "simple_feature_space.h"
#include "simple_feature_value.h"

namespace pomdp
{

/**
 * A constant to avoid magic numbers.
 *
 * Bland name because there's only a single feature.
 */
const std::string DEFAULT_NAME = "feature space";

SimpleFeatureSpace::SimpleFeatureSpace()
{
 SimpleFeatureSpace(0);
}

SimpleFeatureSpace::SimpleFeatureSpace(unsigned int num_states, const std::vector<std::string>& name_mapping)
{
  SimpleFeatureSpace(num_states, boost::make_shared<Pretty>(name_mapping));

  if(feature_.num_states_ >= 2)
    is_init_ = true;
}

SimpleFeatureSpace::SimpleFeatureSpace(unsigned int num_states, shared_ptr<const Pretty> name_mapping)
{
  feature_.name_ = DEFAULT_NAME;
  feature_.num_states_ = num_states;
  feature_.state_name_mapping_ = name_mapping;

  if(feature_.num_states_ >= 2)
    is_init_ = true;
}

SimpleFeatureSpace::~SimpleFeatureSpace()
{
}

bool SimpleFeatureSpace::loadFromYAML(const YAML::Node& feature_space_root)
{
  try
  {
    // Read name
    feature_space_root >> feature_;

    // Sanity checks.
    if((int)feature_.num_states_ < 0) // Negative number of states
    {
      ROS_ERROR_STREAM("Negative number of states " << (int)feature_.num_states_ << " in SimpleFeatureSpace '"
                       << feature_.name_ << "'");
      return false;
    }
    if(feature_.num_states_ < 2)
    {
      ROS_ERROR_STREAM("Number of states " << (int)feature_.num_states_ << " in SimpleFeatureSpace '" << feature_.name_
                       << "' too short for meaningful state space.");
      return false;
    }
  }
  catch(YAML::Exception& e)
  {
    ROS_ERROR_STREAM(e.what());
    return false;
  }
  return true;
}

bool SimpleFeatureSpace::isValid(const FeatureValue& state) const
{
  if(typeid(state) == typeid(SimpleFeatureValue))
    return isValid(dynamic_cast<const SimpleFeatureValue&>(state));
  else if(typeid(state) == typeid(BeliefFeatureValue))
    return isValid(dynamic_cast<const BeliefFeatureValue&>(state));
  else
    return false;
}

bool SimpleFeatureSpace::isValid(const SimpleFeatureValue& state) const
{
  return state.asInt() < getNumValues();
}

bool SimpleFeatureSpace::isValid(const BeliefFeatureValue& belief) const
{
  return belief.asVector().size() == getNumValues();
}

std::string SimpleFeatureSpace::toString() const
{
  std::stringstream ret;
  ret << "SimpleFeatureSpace, has " << feature_;
  return std::string(ret.str());
}

/**
 * Converts a FeatureValue into a name (MDPStates) or a list of probabilities (POMDPStates).
 *
 * @param s The state.
 * @return Stringified State.
 */
std::string SimpleFeatureSpace::toString(const FeatureValue& state) const
{
  std::stringstream ret;
  ret << boost::units::detail::demangle(typeid(state).name());
  if(typeid(state) == typeid(SimpleFeatureValue))
    ret << ": " << toString(dynamic_cast<const SimpleFeatureValue&>(state));
  else if(typeid(state) == typeid(BeliefFeatureValue))
    ret << ": " << toString(dynamic_cast<const BeliefFeatureValue&>(state));
  return ret.str();
}

std::string SimpleFeatureSpace::toString(const SimpleFeatureValue& state) const
{
  return feature_.state_name_mapping_->toString(state.asInt());
}

std::string SimpleFeatureSpace::toString(const BeliefFeatureValue& belief) const
{
  return Pretty::vectorToString(belief.asVector());
}

/**
 * Reads a feature value from a string.
 *
 * String must be either a name contained in this state space (e.g. "go_left") or a number within range (e.g. 4).
 *
 * @param str String representation of the value.
 * @return A SimpleFeatureValue. Value is invalid on failure.
 */
shared_ptr<FeatureValue> SimpleFeatureSpace::readFeatureValue(const std::string& str) const
{
  const unsigned int INVALID_VALUE = INT_MAX;

  int value = Pretty::readNameOrNum(str, feature_.state_name_mapping_);
  if(value == -1)
    return boost::make_shared<SimpleFeatureValue>(INVALID_VALUE);
  else
    return boost::make_shared<SimpleFeatureValue>(value); // Doesn't check for validity - that will be done when isValid is called.
}

void SimpleFeatureSpace::toXmlRpcValue(XmlRpc::XmlRpcValue& v) const
{
  using namespace XmlRpc;

  // Gets value names if they exist or stringified numbers if they don't.
  std::vector<std::string> value_names;
  for(unsigned int i = 0; i < feature_.num_states_; i++)
  {
    value_names.push_back(feature_.state_name_mapping_->toString(i));
  }

  //
  // Create child nodes.
  //
  XmlRpcValue name(feature_.name_);

  // xmlRpcValue(std::vector) would go here
  XmlRpcValue values;
  values.setSize(value_names.size()); // Converts xmlRpcValue to a vector type.

  // Copy the contents into the XmlRpcValue
  for(size_t i=0; i < value_names.size(); i++) {
    values[i] = value_names.at(i);
  }

  //
  // Add children to parent node.
  //
  v["name"] = name;
  v["values"] = values;
}

} /* namespace pomdp */


text:
#include "RegexCHashExtractor.h"
#include "../ContentNormalizationModule/ContentNormalizationModule.h"
#include "../ContentExtractionModule/ContentExtractionModule.h"
#include "../Datatypes/EnumTypes.h"
#include <boost/regex.hpp>
#include <boost/algorithm/string.hpp>

namespace PDLS {

    ContentHash* RegexCHashExtractor::extractContentHash(Document* doc, const std::string& hashPrefix, const std::string& hashPostfix) {
        if(!doc)
            throw NullPointerException("RegexCHashExtractor::extractContentHash");

        Content* dc = nullptr;
        if(!doc->getContent()) {
            dc = extractDocumentContent(doc);
            doc->setContent(dc);
        }
        else
            dc = doc->getContent();

        boost::regex expression(hashPrefix + *_contentHashMatcherMap[_expectedHashType] + hashPostfix);
        boost::match_results<std::string::const_iterator> results; //container to store regex matches

        //search hash pattern
        if (boost::regex_search(dc->getValue(), results, expression)) {
            if(results.size() > 1)
                throw TooManyContentHashesException(doc->getPath());

            std::string contentHashString = results.str();

            //remove hash from content
            std::string tmp(dc->getValue());
            boost::erase_all(tmp, contentHashString);
            dc->setValue(tmp);

            return new ContentHash(_expectedHashType, contentHashString, hashPrefix, hashPostfix);

        } else
            throw MissingContentHashException(doc->getPath());

    }

    void RegexCHashExtractor::generateContentHashMatcherMap() {
        _contentHashMatcherMap.insert(std::make_pair(ContentHashType::MD5, new std::string("[A-Fa-f0-9]{32}")));
        _contentHashMatcherMap.insert(std::make_pair(ContentHashType::SHA1, new std::string("[A-Fa-f0-9]{40}")));
        _contentHashMatcherMap.insert(std::make_pair(ContentHashType::SHA224, new std::string("[A-Fa-f0-9]{56}")));
        _contentHashMatcherMap.insert(std::make_pair(ContentHashType::SHA256, new std::string("[A-Fa-f0-9]{64}")));
        _contentHashMatcherMap.insert(std::make_pair(ContentHashType::SHA384, new std::string("[A-Fa-f0-9]{96}")));
        _contentHashMatcherMap.insert(std::make_pair(ContentHashType::SHA512, new std::string("[A-Fa-f0-9]{128}")));
    }

    RegexCHashExtractor::RegexCHashExtractor(const ContentHashType& hT) : IContentHashExtractor(hT) {
        generateContentHashMatcherMap();
    }

    Content* RegexCHashExtractor::extractDocumentContent(Document* doc) {
        if(!doc)
            throw NullPointerException("RegexCHashExtractor::extractDocumentContent");

        ContentExtractionModule* cem = ContentExtractionModule::getInstance();
        Content* dc = cem->extractContent(doc);
        return dc;
    }

}

max_stars_repo_name: floschne/BachelorThesis

max_issues_repo_name: floschne/BachelorThesis

max_forks_repo_name: floschne/BachelorThesis