<commit_before>//-----------------------------------------------
//
//	This file is part of the HamFramework for Siv3D.
//
//	Copyright (C) 2014-2016 Hamukun
//	Copyright (C) 2014-2016 Ryo Suzuki
//
//	Licensed under the MIT License.
//
//-----------------------------------------------

# pragma once
//# include "../Siv3D.hpp"
# include <Siv3D.hpp>

namespace ham
{
	enum class TransitionState
	{
		None,
		FadeIn,
		Active,
		FadeOut,
		FadeInOut,
	};

	template<class State, class Data> class LayerManager;

	template<class State, class Data>
	class LayerBase : public std::enable_shared_from_this<LayerBase<State, Data>>, s3d::Uncopyable
	{
	public:

		using Manager_t = LayerManager<State, Data>;

		using State_t = State;

		using Data_t = Data;

		virtual ~LayerBase() = default;

		void setData(Manager_t* pManager, const std::shared_ptr<Data>& data)
		{
			m_manager = pManager;

			m_data = data;
		}

		void setTransitionValue(int transitionTimeMillisec)
		{
			m_transitionTimeMillisec = transitionTimeMillisec;

			m_transitionState = TransitionState::FadeIn;

			m_stopwatch.restart();
		}

		s3d::Stopwatch& getStopwatch()
		{
			return m_stopwatch;
		}

		int32 getTransitionTimeMillisec() const
		{
			return m_transitionTimeMillisec;
		}

		void setTransitionState(const TransitionState& transitionState)
		{
			m_transitionState = transitionState;
		}

		const TransitionState& getTransitionState() const
		{
			return m_transitionState;
		}

		bool isDestroyed() const
		{
			return m_isDestroyed;
		}

		void setDestroyed(bool isDestroyed)
		{
			m_isDestroyed = isDestroyed;
		}

		virtual void init() {}

		virtual bool input() { return false; }

		virtual bool inputFadeIn(double) { return false; }

		virtual bool inputFadeOut(double) { return false; }

		virtual void updateFadeIn(double) {}

		virtual void update() = 0;

		virtual void updateFadeOut(double) {}

		virtual void draw() const = 0;

		virtual void drawFadeIn(double) const
		{
			draw();
		}

		virtual void drawFadeOut(double) const
		{
			draw();
		}

	protected:

		std::shared_ptr<Data> m_data;

		bool pushLayer(const State& state, int transitionTimeMillisec = 200)
		{
			return m_manager->pushLayer(state, transitionTimeMillisec);
		}

		bool popThisLayer()
		{
			return m_manager->popLayer(shared_from_this());
		}

	private:

		Manager_t* m_manager = nullptr;

		s3d::Stopwatch m_stopwatch;

		int32 m_transitionTimeMillisec = 0;

		TransitionState m_transitionState = TransitionState::None;

		bool m_isDestroyed = false;
	};

	template<class State, class Data> class LayerManager
	{
	private:

		using Layer_t = std::shared_ptr<LayerBase<State, Data>>;

		using FactoryFunction_t = std::function<Layer_t()>;

		std::unordered_map<State, FactoryFunction_t> m_factories;

		std::shared_ptr<Data> m_data;

		Array<Layer_t> m_layers;

		Array<Layer_t> m_tLayers;

		s3d::Optional<State> m_first;

		bool m_error = false;

		template<class Type>
		std::shared_ptr<Type> MakeShared() const
		{
			return std::make_shared<Data>();
		}

		template<>
		std::shared_ptr<void> MakeShared() const
		{
			return std::shared_ptr<void>(nullptr);
		}

	public:

		using Layer = LayerBase<State, Data>;

		LayerManager()
			: m_data(MakeShared<Data>())
		{

		}

		LayerManager(const std::shared_ptr<Data>& data)
			: m_data(data)
		{

		}

		template<class Layer> bool add(const State& state)
		{
			if (m_factories.find(state) != m_factories.end())
			{
				return false;
			}

			m_factories.emplace(state, [&]()
			{
				auto m = std::make_shared<Layer>();

				m->setData(this, m_data);

				return m;
			});

			if (!m_first)
			{
				m_first = state;
			}

			return true;
		}

		bool init(const State& state)
		{
			if (m_layers.size() != 0)
			{
				m_layers.clear();
			}

			auto it = m_factories.find(state);

			if (it == m_factories.end())
			{
				return false;
			}

			auto newLayer = it->second();

			newLayer->init();

			m_layers.push_back(newLayer);

			return true;
		}

		bool input()
		{
			for (auto i = m_layers.rbegin(); i != m_layers.rend(); ++i)
			{
				auto& layer = *i;

				const auto state = layer->getTransitionState();

				if (state == TransitionState::FadeIn || state == TransitionState::Active)
				{
					if (layer->input())
					{
						break;
					}
				}
			}

			if (m_tLayers.size() > 0)
			{
				m_layers.insert(m_layers.end(), m_tLayers.begin(), m_tLayers.end());

				m_tLayers.clear();
			}

			return true;
		}

		bool update()
		{
			if (m_layers.size() == 0 && !init(m_first.value()))
			{
				return false;
			}

			for (auto& layer : m_layers)
			{
				const int32 elapsed = layer->getStopwatch().ms();

				switch (layer->getTransitionState())
				{
				case TransitionState::FadeIn:
					layer->updateFadeIn(static_cast<double>(elapsed) / layer->getTransitionTimeMillisec());
					if (elapsed > layer->getTransitionTimeMillisec())
					{
						layer->getStopwatch().reset();
						layer->setTransitionState(TransitionState::Active);
					}
					break;
				case TransitionState::Active:
					layer->update();
					break;
				case TransitionState::FadeOut:
					layer->updateFadeOut(static_cast<double>(elapsed) / layer->getTransitionTimeMillisec());
					if (elapsed > layer->getTransitionTimeMillisec())
					{
						layer->setDestroyed(true);
					}
					break;
				default:
					break;
				}
			}

			Erase_if(m_layers, [&](const Layer_t& layer)
			{
				return layer->isDestroyed();
			});

			if (m_tLayers.size() > 0)
			{
				m_layers.insert(m_layers.end(), m_tLayers.begin(), m_tLayers.end());

				m_tLayers.clear();
			}

			return true;
		}

		void draw() const
		{
			for (const auto& layer : m_layers)
			{
				const int32 elapsed = layer->getStopwatch().ms();

				switch (layer->getTransitionState())
				{
				case TransitionState::FadeIn:
					layer->drawFadeIn(static_cast<double>(elapsed) / layer->getTransitionTimeMillisec());
					break;
				case TransitionState::Active:
					layer->draw();
					break;
				case TransitionState::FadeOut:
					layer->drawFadeOut(static_cast<double>(elapsed) / layer->getTransitionTimeMillisec());
					break;
				default:
					break;
				}
			}
		}

		bool inputAndUpdateAndDraw()
		{
			if (!input())
			{
				return false;
			}

			if (!update())
			{
				return false;
			}

			draw();

			return true;
		}

		std::shared_ptr<Data> get()
		{
			return m_data;
		}

		bool pushLayer(const State& state, int transitionTimeMillisec = 200)
		{
			if (m_factories.find(state) == m_factories.end())
			{
				return false;
			}

			auto newLayer = m_factories[state]();

			newLayer->setTransitionValue(transitionTimeMillisec);

			newLayer->init();

			m_tLayers.push_back(newLayer);

			return true;
		}

		bool popLayer(const std::shared_ptr<Layer>& layer)
		{
			auto it = std::find(m_layers.begin(), m_layers.end(), layer);

			if (it == m_layers.end())
			{
				return false;
			}

			(*it)->setTransitionState(TransitionState::FadeOut);
			(*it)->getStopwatch().restart();

			return true;
		}
	};
}
<commit_msg>fix init<commit_after>//-----------------------------------------------
//
//	This file is part of the HamFramework for Siv3D.
//
//	Copyright (C) 2014-2016 Hamukun
//	Copyright (C) 2014-2016 Ryo Suzuki
//
//	Licensed under the MIT License.
//
//-----------------------------------------------

# pragma once
//# include "../Siv3D.hpp"
# include <Siv3D.hpp>

namespace ham
{
	enum class TransitionState
	{
		None,
		FadeIn,
		Active,
		FadeOut,
		FadeInOut,
	};

	template<class State, class Data> class LayerManager;

	template<class State, class Data>
	class LayerBase : public std::enable_shared_from_this<LayerBase<State, Data>>, s3d::Uncopyable
	{
	public:

		using Manager_t = LayerManager<State, Data>;

		using State_t = State;

		using Data_t = Data;

		virtual ~LayerBase() = default;

		void setData(Manager_t* pManager, const std::shared_ptr<Data>& data)
		{
			m_manager = pManager;

			m_data = data;
		}

		void setTransitionValue(int transitionTimeMillisec)
		{
			m_transitionTimeMillisec = transitionTimeMillisec;

			m_transitionState = TransitionState::FadeIn;

			m_stopwatch.restart();
		}

		s3d::Stopwatch& getStopwatch()
		{
			return m_stopwatch;
		}

		int32 getTransitionTimeMillisec() const
		{
			return m_transitionTimeMillisec;
		}

		void setTransitionState(const TransitionState& transitionState)
		{
			m_transitionState = transitionState;
		}

		const TransitionState& getTransitionState() const
		{
			return m_transitionState;
		}

		bool isDestroyed() const
		{
			return m_isDestroyed;
		}

		void setDestroyed(bool isDestroyed)
		{
			m_isDestroyed = isDestroyed;
		}

		virtual void init() {}

		virtual bool input() { return false; }

		virtual bool inputFadeIn(double) { return false; }

		virtual bool inputFadeOut(double) { return false; }

		virtual void updateFadeIn(double) {}

		virtual void update() = 0;

		virtual void updateFadeOut(double) {}

		virtual void draw() const = 0;

		virtual void drawFadeIn(double) const
		{
			draw();
		}

		virtual void drawFadeOut(double) const
		{
			draw();
		}

	protected:

		std::shared_ptr<Data> m_data;

		bool pushLayer(const State& state, int transitionTimeMillisec = 200)
		{
			return m_manager->pushLayer(state, transitionTimeMillisec);
		}

		bool popThisLayer()
		{
			return m_manager->popLayer(shared_from_this());
		}

	private:

		Manager_t* m_manager = nullptr;

		s3d::Stopwatch m_stopwatch;

		int32 m_transitionTimeMillisec = 0;

		TransitionState m_transitionState = TransitionState::None;

		bool m_isDestroyed = false;
	};

	template<class State, class Data> class LayerManager
	{
	private:

		using Layer_t = std::shared_ptr<LayerBase<State, Data>>;

		using FactoryFunction_t = std::function<Layer_t()>;

		std::unordered_map<State, FactoryFunction_t> m_factories;

		std::shared_ptr<Data> m_data;

		Array<Layer_t> m_layers;

		Array<Layer_t> m_tLayers;

		s3d::Optional<State> m_first;

		bool m_error = false;

		template<class Type>
		std::shared_ptr<Type> MakeShared() const
		{
			return std::make_shared<Data>();
		}

		template<>
		std::shared_ptr<void> MakeShared() const
		{
			return std::shared_ptr<void>(nullptr);
		}

	public:

		using Layer = LayerBase<State, Data>;

		LayerManager()
			: m_data(MakeShared<Data>())
		{

		}

		LayerManager(const std::shared_ptr<Data>& data)
			: m_data(data)
		{

		}

		template<class Layer> bool add(const State& state)
		{
			if (m_factories.find(state) != m_factories.end())
			{
				return false;
			}

			m_factories.emplace(state, [&]()
			{
				auto m = std::make_shared<Layer>();

				m->setData(this, m_data);

				return m;
			});

			if (!m_first)
			{
				m_first = state;
			}

			return true;
		}

		bool init(const State& state)
		{
			if (m_layers.size() != 0)
			{
				m_layers.clear();
			}

			auto it = m_factories.find(state);

			if (it == m_factories.end())
			{
				return false;
			}

			auto newLayer = it->second();

			newLayer->init();

			m_layers.push_back(newLayer);

			return true;
		}

		bool input()
		{
			for (auto i = m_layers.rbegin(); i != m_layers.rend(); ++i)
			{
				auto& layer = *i;

				const auto state = layer->getTransitionState();

				if (state == TransitionState::FadeIn || state == TransitionState::Active)
				{
					if (layer->input())
					{
						break;
					}
				}
			}

			if (m_tLayers.size() > 0)
			{
				m_layers.insert(m_layers.end(), m_tLayers.begin(), m_tLayers.end());

				m_tLayers.clear();
			}

			return true;
		}

		bool update()
		{
			if (m_layers.size() == 0 && !init(m_first.value()))
			{
				return false;
			}

			for (auto& layer : m_layers)
			{
				const int32 elapsed = layer->getStopwatch().ms();

				switch (layer->getTransitionState())
				{
				case TransitionState::FadeIn:
					layer->updateFadeIn(static_cast<double>(elapsed) / layer->getTransitionTimeMillisec());
					if (elapsed > layer->getTransitionTimeMillisec())
					{
						layer->getStopwatch().reset();
						layer->setTransitionState(TransitionState::Active);
					}
					break;
				case TransitionState::Active:
					layer->update();
					break;
				case TransitionState::FadeOut:
					layer->updateFadeOut(static_cast<double>(elapsed) / layer->getTransitionTimeMillisec());
					if (elapsed > layer->getTransitionTimeMillisec())
					{
						layer->setDestroyed(true);
					}
					break;
				default:
					break;
				}
			}

			Erase_if(m_layers, [&](const Layer_t& layer)
			{
				return layer->isDestroyed();
			});

			if (m_tLayers.size() > 0)
			{
				m_layers.insert(m_layers.end(), m_tLayers.begin(), m_tLayers.end());

				m_tLayers.clear();
			}

			return true;
		}

		void draw() const
		{
			for (const auto& layer : m_layers)
			{
				const int32 elapsed = layer->getStopwatch().ms();

				switch (layer->getTransitionState())
				{
				case TransitionState::FadeIn:
					layer->drawFadeIn(static_cast<double>(elapsed) / layer->getTransitionTimeMillisec());
					break;
				case TransitionState::Active:
					layer->draw();
					break;
				case TransitionState::FadeOut:
					layer->drawFadeOut(static_cast<double>(elapsed) / layer->getTransitionTimeMillisec());
					break;
				default:
					break;
				}
			}
		}

		bool inputAndUpdateAndDraw()
		{
			if (!input())
			{
				return false;
			}

			if (!update())
			{
				return false;
			}

			draw();

			return true;
		}

		std::shared_ptr<Data> get()
		{
			return m_data;
		}

		bool pushLayer(const State& state, int transitionTimeMillisec = 200)
		{
			if (m_factories.find(state) == m_factories.end())
			{
				return false;
			}

			auto newLayer = m_factories[state]();

			newLayer->setTransitionValue(transitionTimeMillisec);

			m_tLayers.push_back(newLayer);

			newLayer->init();

			return true;
		}

		bool popLayer(const std::shared_ptr<Layer>& layer)
		{
			auto it = std::find(m_layers.begin(), m_layers.end(), layer);

			if (it == m_layers.end())
			{
				return false;
			}

			(*it)->setTransitionState(TransitionState::FadeOut);
			(*it)->getStopwatch().restart();

			return true;
		}
	};
}
<|endoftext|>


<commit_before>/***********************************************************************************************************************
 **
 ** Copyright (c) 2011, 2015 ETH Zurich
 ** 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 ETH Zurich 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 HOLDER 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.
 **
 **********************************************************************************************************************/

#include "CodeComposite.h"

#include "Export/src/tree/CompositeFragment.h"
#include "OOModel/src/declarations/Class.h"

namespace CppExport {

CodeComposite::CodeComposite(const QString& name) : name_{name} {}

void CodeComposite::addUnit(CodeUnit* unit)
{
	units_.append(unit);
	// assert every unit belongs to only one composite
	Q_ASSERT(!unit->composite());
	unit->setComposite(this);
}

QString CodeComposite::relativePath(CodeComposite* other)
{
	QStringList otherName = other->name().split("/");

	if (name() == other->name()) return otherName.last();

	QStringList thisName = name().split("/");
	while (thisName.first() == otherName.first())
	{
		thisName.takeFirst();
		otherName.takeFirst();
	}

	int backSteps = thisName.size() - otherName.size();
	for (auto i = 0; i < backSteps; i++) otherName.prepend("..");
	return otherName.join("/");
}

QSet<Model::Node*> CodeComposite::reduceSoftDependencies(QSet<CodeComposite*> hardDependencies,
																			QSet<Model::Node*> softDependencies)
{
	auto result = softDependencies;
	auto workList = QList<CodeComposite*>::fromSet(hardDependencies);
	QSet<CodeComposite*> processed;

	while (!workList.empty())
	{
		auto hardDependency = workList.takeFirst();

		if (!processed.contains(hardDependency))
		{
			for (auto unit : hardDependency->units())
			{
				for (auto transitiveDependencyHeaderPart : unit->headerPart()->dependencies())
					workList.append(transitiveDependencyHeaderPart->parent()->composite());

				for (auto softDependency : softDependencies)
					if (result.contains(softDependency))
						if (unit->node() == softDependency || unit->node()->isAncestorOf(softDependency))
							result.remove(softDependency);
			}

			processed.insert(hardDependency);
		}
	}

	return result;
}

Export::SourceFragment* CodeComposite::partFragment(CodeUnitPart* (CodeUnit::*part) ())
{
	Q_ASSERT(!units().empty());

	QSet<Model::Node*> softDependencies;
	QSet<CodeComposite*> compositeDependencies;
	for (auto unit : units())
		for (CodeUnitPart* dependency : (unit->*part)()->dependencies())
		{
			softDependencies.unite(dependency->softDependencies());
			compositeDependencies.insert(dependency->parent()->composite());
		}

	auto composite = new Export::CompositeFragment(units().first()->node());
	if (!compositeDependencies.empty())
	{
		for (auto compositeDependency : compositeDependencies)
				*composite << "#include \"" + relativePath(compositeDependency) + ".h\"\n";

		*composite << "\n";
	}

	auto softDependenciesReduced = reduceSoftDependencies(compositeDependencies, softDependencies);
	if (!softDependenciesReduced.empty())
	{
		for (auto softDependency : softDependenciesReduced)
		{
			if (auto classs = DCast<OOModel::Class>(softDependency))
			{
				if (OOModel::Class::ConstructKind::Class == classs->constructKind()) *composite << "class ";
				else if (OOModel::Class::ConstructKind::Struct == classs->constructKind()) *composite << "struct ";
				else if (OOModel::Class::ConstructKind::Enum == classs->constructKind()) *composite << "enum ";
				else Q_ASSERT(false);
			}
			else
				Q_ASSERT(false);

			*composite << softDependency->symbolName() + ";\n";
		}

		*composite << "\n";
	}

	if (!units().isEmpty())
	{
		OOModel::Module* currentNamespace{};

		for (auto unit : units())
		{
			auto neededNamespace = unit->node()->firstAncestorOfType<OOModel::Module>();

			if (neededNamespace != currentNamespace)
			{
				if (currentNamespace) *composite << "\n}\n\n";
				if (neededNamespace) *composite << "namespace " << neededNamespace->symbolName() << " {\n\n";
				currentNamespace = neededNamespace;
			}

			composite->append((unit->*part)()->sourceFragment());
		}

		if (currentNamespace) *composite << "\n}";
	}

	return composite;
}

Export::SourceFragment* CodeComposite::addPragmaOnce(Export::SourceFragment* fragment)
{
	auto compositeFragment = new Export::CompositeFragment(fragment->node());
	*compositeFragment << "#pragma once\n\n" << fragment;
	return compositeFragment;
}

void CodeComposite::sortUnits()
{
	if (units().size() <= 1) return;

	QHash<CodeUnitPart*, QSet<CodeUnitPart*>> headerPartDependencies;
	for (auto unit : units()) headerPartDependencies.insert(unit->headerPart(), unit->headerPart()->dependencies());

	units_.clear();
	for (auto headerPart : topologicalSort(headerPartDependencies)) units_.append(headerPart->parent());
}

void CodeComposite::fragments(Export::SourceFragment*& header, Export::SourceFragment*& source)
{
	sortUnits();
	header = headerFragment();
	source = sourceFragment();
}

template <typename T>
QList<T*> CodeComposite::topologicalSort(QHash<T*, QSet<T*>> dependsOn)
{
	// calculate a list of elements with no dependencies.
	// calculate a map that maps from an element to all elements that depend on it.
	QList<T*> noPendingDependencies;
	QHash<T*, QSet<T*>> neededFor;
	for (auto it = dependsOn.begin(); it != dependsOn.end(); it++)
		if (it.value().empty())
			// this element depends on no other elements
			noPendingDependencies.append(it.key());
		else
			// for every other element this element depends on add it to the neededFor map for said other element
			for (auto dependency : it.value())
				neededFor[dependency].insert(it.key());

	QList<T*> result;
	while (!noPendingDependencies.empty())
	{
		// take any item form the list of item with no more dependencies and add it to the result
		auto n = noPendingDependencies.takeFirst();
		result.append(n);

		// check if we are neededFor another node
		auto it = neededFor.find(n);
		if (it == neededFor.end()) continue;

		// for every node we are neededFor
		for (auto m : *it)
		{
			// find the nodes the node we are needed for dependsOn
			auto dIt = dependsOn.find(m);
			Q_ASSERT(dIt != dependsOn.end());

			// remove us from its dependencies
			dIt->remove(n);

			// if this node has no more dependencies add it to the list of items with no more dependencies
			if (dIt->size() == 0)
				noPendingDependencies.append(m);
		}
	}

	// test graph for cycles
	for (auto dependencies : dependsOn.values())
		Q_ASSERT(dependencies.empty());

	return result;
}

}
<commit_msg>prevent file creation for empty files<commit_after>/***********************************************************************************************************************
 **
 ** Copyright (c) 2011, 2015 ETH Zurich
 ** 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 ETH Zurich 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 HOLDER 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.
 **
 **********************************************************************************************************************/

#include "CodeComposite.h"

#include "Export/src/tree/CompositeFragment.h"
#include "OOModel/src/declarations/Class.h"

namespace CppExport {

CodeComposite::CodeComposite(const QString& name) : name_{name} {}

void CodeComposite::addUnit(CodeUnit* unit)
{
	units_.append(unit);
	// assert every unit belongs to only one composite
	Q_ASSERT(!unit->composite());
	unit->setComposite(this);
}

QString CodeComposite::relativePath(CodeComposite* other)
{
	QStringList otherName = other->name().split("/");

	if (name() == other->name()) return otherName.last();

	QStringList thisName = name().split("/");
	while (thisName.first() == otherName.first())
	{
		thisName.takeFirst();
		otherName.takeFirst();
	}

	int backSteps = thisName.size() - otherName.size();
	for (auto i = 0; i < backSteps; i++) otherName.prepend("..");
	return otherName.join("/");
}

QSet<Model::Node*> CodeComposite::reduceSoftDependencies(QSet<CodeComposite*> hardDependencies,
																			QSet<Model::Node*> softDependencies)
{
	auto result = softDependencies;
	auto workList = QList<CodeComposite*>::fromSet(hardDependencies);
	QSet<CodeComposite*> processed;

	while (!workList.empty())
	{
		auto hardDependency = workList.takeFirst();

		if (!processed.contains(hardDependency))
		{
			for (auto unit : hardDependency->units())
			{
				for (auto transitiveDependencyHeaderPart : unit->headerPart()->dependencies())
					workList.append(transitiveDependencyHeaderPart->parent()->composite());

				for (auto softDependency : softDependencies)
					if (result.contains(softDependency))
						if (unit->node() == softDependency || unit->node()->isAncestorOf(softDependency))
							result.remove(softDependency);
			}

			processed.insert(hardDependency);
		}
	}

	return result;
}

Export::SourceFragment* CodeComposite::partFragment(CodeUnitPart* (CodeUnit::*part) ())
{
	Q_ASSERT(!units().empty());

	QSet<Model::Node*> softDependencies;
	QSet<CodeComposite*> compositeDependencies;
	for (auto unit : units())
		for (CodeUnitPart* dependency : (unit->*part)()->dependencies())
		{
			softDependencies.unite(dependency->softDependencies());
			compositeDependencies.insert(dependency->parent()->composite());
		}

	auto composite = new Export::CompositeFragment(units().first()->node());
	if (!compositeDependencies.empty())
	{
		for (auto compositeDependency : compositeDependencies)
				*composite << "#include \"" + relativePath(compositeDependency) + ".h\"\n";

		*composite << "\n";
	}

	auto softDependenciesReduced = reduceSoftDependencies(compositeDependencies, softDependencies);
	if (!softDependenciesReduced.empty())
	{
		for (auto softDependency : softDependenciesReduced)
		{
			if (auto classs = DCast<OOModel::Class>(softDependency))
			{
				if (OOModel::Class::ConstructKind::Class == classs->constructKind()) *composite << "class ";
				else if (OOModel::Class::ConstructKind::Struct == classs->constructKind()) *composite << "struct ";
				else if (OOModel::Class::ConstructKind::Enum == classs->constructKind()) *composite << "enum ";
				else Q_ASSERT(false);
			}
			else
				Q_ASSERT(false);

			*composite << softDependency->symbolName() + ";\n";
		}

		*composite << "\n";
	}

	bool hasMeaningfulContent = false;
	if (!units().isEmpty())
	{
		OOModel::Module* currentNamespace{};

		for (auto unit : units())
		{
			auto codeUnitPart = (unit->*part)();
			if (codeUnitPart->isSourceFragmentEmpty()) continue;

			auto neededNamespace = unit->node()->firstAncestorOfType<OOModel::Module>();
			if (neededNamespace != currentNamespace)
			{
				if (currentNamespace) *composite << "\n}\n\n";
				if (neededNamespace) *composite << "namespace " << neededNamespace->symbolName() << " {\n\n";
				currentNamespace = neededNamespace;
			}

			composite->append(codeUnitPart->sourceFragment());
			hasMeaningfulContent = true;
		}

		if (currentNamespace) *composite << "\n}";
	}

	if (!hasMeaningfulContent)
	{
		SAFE_DELETE(composite);
		return nullptr;
	}
	return composite;
}

Export::SourceFragment* CodeComposite::addPragmaOnce(Export::SourceFragment* fragment)
{
	auto compositeFragment = new Export::CompositeFragment(fragment->node());
	*compositeFragment << "#pragma once\n\n" << fragment;
	return compositeFragment;
}

void CodeComposite::sortUnits()
{
	if (units().size() <= 1) return;

	QHash<CodeUnitPart*, QSet<CodeUnitPart*>> headerPartDependencies;
	for (auto unit : units()) headerPartDependencies.insert(unit->headerPart(), unit->headerPart()->dependencies());

	units_.clear();
	for (auto headerPart : topologicalSort(headerPartDependencies)) units_.append(headerPart->parent());
}

void CodeComposite::fragments(Export::SourceFragment*& header, Export::SourceFragment*& source)
{
	sortUnits();
	header = headerFragment();
	source = sourceFragment();
}

template <typename T>
QList<T*> CodeComposite::topologicalSort(QHash<T*, QSet<T*>> dependsOn)
{
	// calculate a list of elements with no dependencies.
	// calculate a map that maps from an element to all elements that depend on it.
	QList<T*> noPendingDependencies;
	QHash<T*, QSet<T*>> neededFor;
	for (auto it = dependsOn.begin(); it != dependsOn.end(); it++)
		if (it.value().empty())
			// this element depends on no other elements
			noPendingDependencies.append(it.key());
		else
			// for every other element this element depends on add it to the neededFor map for said other element
			for (auto dependency : it.value())
				neededFor[dependency].insert(it.key());

	QList<T*> result;
	while (!noPendingDependencies.empty())
	{
		// take any item form the list of item with no more dependencies and add it to the result
		auto n = noPendingDependencies.takeFirst();
		result.append(n);

		// check if we are neededFor another node
		auto it = neededFor.find(n);
		if (it == neededFor.end()) continue;

		// for every node we are neededFor
		for (auto m : *it)
		{
			// find the nodes the node we are needed for dependsOn
			auto dIt = dependsOn.find(m);
			Q_ASSERT(dIt != dependsOn.end());

			// remove us from its dependencies
			dIt->remove(n);

			// if this node has no more dependencies add it to the list of items with no more dependencies
			if (dIt->size() == 0)
				noPendingDependencies.append(m);
		}
	}

	// test graph for cycles
	for (auto dependencies : dependsOn.values())
		Q_ASSERT(dependencies.empty());

	return result;
}

}
<|endoftext|>


<commit_before>/* Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */

#include <algorithm>
#include <fstream>
#include <iostream>
#include "paddle/fluid/inference/tests/api/tester_helper.h"

namespace paddle {
namespace inference {
namespace analysis {

struct OneSlotInBatch {
  std::string name;
  std::vector<std::vector<float>> data;
  std::vector<int> shape;
  std::vector<size_t> lod;
};

struct DataRecord {
  std::vector<std::vector<OneSlotInBatch>> batched_data;
  std::map<std::string, std::vector<std::vector<float>>> datasets;
  size_t batch_iter{0}, num_samples;  // total number of samples

  DataRecord() = default;
  explicit DataRecord(const std::string &path, int batch_size = 1) {
    Load(path);
    Prepare(batch_size);
  }

  void Load(const std::string &path) {
    std::ifstream file(path);
    constexpr int num_slots = 154;
    std::string line;
    int num_lines = 0;
    while (std::getline(file, line)) {
      num_lines++;
      std::vector<std::string> data;
      split(line, '\t', &data);
      std::vector<float> slot_data;
      split_to_float(data[1], ' ', &slot_data);
      std::string name = data[0];
      PADDLE_ENFORCE_EQ(slot_data.size() % 11, 0,
                        "line %d, %s should be divisible", num_lines, name);
      datasets[name].emplace_back(std::move(slot_data));
    }
    num_samples = num_lines / num_slots;
    PADDLE_ENFORCE_EQ(num_samples * num_slots, static_cast<size_t>(num_lines),
                      "num samples should be divisible");
    PADDLE_ENFORCE_GT(num_samples, 0);
  }

  void Prepare(int bs) {
    for (auto it = datasets.begin(); it != datasets.end(); ++it) {
      PADDLE_ENFORCE_EQ(it->second.size(), num_samples,
                        "size of each slot should be equal");
    }
    size_t num_batches = num_samples / bs;
    EXPECT_GT(num_batches, 0);
    batched_data.resize(num_batches);
    for (auto &one_batch : batched_data) {
      one_batch.resize(datasets.size());
      size_t i = 0;
      for (auto it = datasets.begin(); it != datasets.end(); ++it) {
        auto &slot = one_batch[i];
        slot.name = it->first;
        slot.data.resize(bs);
        slot.lod.resize(bs + 1);
        slot.lod[0] = 0;
        auto &lod = slot.lod;
        auto &datas = it->second;
        for (int k = 0; k < bs; ++k) {
          size_t id = k + batch_iter * bs;
          std::copy(datas[id].begin(), datas[id].end(),
                    std::back_inserter(slot.data[k]));
          size_t len = datas[id].size() / 11;
          PADDLE_ENFORCE_EQ(len * 11, datas[id].size(),
                            "%s %d size should be divisible", slot.name, id);
          lod[k + 1] = lod[k] + len;
        }
        slot.shape.assign({static_cast<int>(lod[bs]), 11});
        i++;
      }
    }
  }

  const std::vector<OneSlotInBatch> &NextBatch() {
    if (batch_iter >= batched_data.size() - 1) {
      batch_iter = -1;
    }
    return batched_data[++batch_iter];
  }
};

static void TensorAssignSlot(PaddleTensor *tensor, const OneSlotInBatch &slot) {
  tensor->name = slot.name + "_embed";
  tensor->shape = slot.shape;
  tensor->dtype = PaddleDType::FLOAT32;
  tensor->lod.clear();
  tensor->lod.emplace_back(slot.lod);
  TensorAssignData(tensor, slot.data);
}

void PrepareInputs(std::vector<PaddleTensor> *input_slots, DataRecord *data) {
  const auto &one_batch = data->NextBatch();
  input_slots->resize(one_batch.size());
  for (size_t i = 0; i < one_batch.size(); ++i) {
    auto &slot = one_batch[i];
    TensorAssignSlot(&((*input_slots)[i]), slot);
  }
}

void SetInput(std::vector<std::vector<PaddleTensor>> *inputs) {
  DataRecord data(FLAGS_infer_data, FLAGS_batch_size);
  std::vector<PaddleTensor> input_slots;
  int epoch = FLAGS_test_all_data ? data.batched_data.size() : 1;
  LOG(INFO) << "number of samples: "
            << data.batched_data.size() * FLAGS_batch_size;
  for (int bid = 0; bid < epoch; ++bid) {
    PrepareInputs(&input_slots, &data);
    (*inputs).emplace_back(input_slots);
  }
}

void SetConfig(AnalysisConfig *cfg, bool use_mkldnn = false) {
  cfg->SetModel(FLAGS_infer_model + "/model", FLAGS_infer_model + "/params");
  cfg->DisableGpu();
  cfg->SwitchSpecifyInputNames();
  cfg->pass_builder()->TurnOnDebug();
  cfg->SetCpuMathLibraryNumThreads(FLAGS_paddle_num_threads);
  if (use_mkldnn) {
    cfg->EnableMKLDNN();
  }
}

void profile(bool use_mkldnn = false) {
  AnalysisConfig cfg;
  SetConfig(&cfg, use_mkldnn);

  std::vector<PaddleTensor> outputs;
  std::vector<std::vector<PaddleTensor>> input_slots_all;
  SetInput(&input_slots_all);
  TestPrediction(reinterpret_cast<const PaddlePredictor::Config *>(&cfg),
                 input_slots_all, &outputs, FLAGS_num_threads);
}

TEST(Analyzer_seq_pool1, profile) { profile(); }

// Compare result of NativeConfig and AnalysisConfig
TEST(Analyzer_seq_pool1, compare) {
  AnalysisConfig cfg;
  SetConfig(&cfg);

  std::vector<std::vector<PaddleTensor>> input_slots_all;
  SetInput(&input_slots_all);
  CompareNativeAndAnalysis(
      reinterpret_cast<const PaddlePredictor::Config *>(&cfg), input_slots_all);
}

void analysis_fuse_statis(bool use_zerocopy) {
  AnalysisConfig cfg;
  SetConfig(&cfg);
  cfg.SwitchUseFeedFetchOps(!use_zerocopy);
  int num_ops;
  auto predictor = CreatePaddlePredictor<AnalysisConfig>(cfg);
  auto fuse_statis = GetFuseStatis(predictor.get(), &num_ops);
  ASSERT_TRUE(fuse_statis.count("fc_fuse"));
  ASSERT_EQ(fuse_statis.at("fc_fuse"), 10);
  ASSERT_TRUE(fuse_statis.count("seqpool_concat_fuse"));
  EXPECT_EQ(fuse_statis.at("seqpool_concat_fuse"), 2);
  LOG(INFO) << "num_ops: " << num_ops;
  EXPECT_EQ(num_ops, 195);
}

// Check the fuse status
TEST(Analyzer_seq_pool1, fuse_statis) { analysis_fuse_statis(false); }

void PrepareZeroCopyInputs(
    const std::unique_ptr<PaddlePredictor> &predictor,
    std::vector<std::unique_ptr<ZeroCopyTensor>> *inputs) {
  DataRecord data(FLAGS_infer_data, FLAGS_batch_size);
  // only feed one batch
  const auto &one_batch = data.NextBatch();
  inputs->clear();
  for (size_t i = 0; i < one_batch.size(); ++i) {
    auto &slot = one_batch[i];
    auto tensor = predictor->GetInputTensor(slot.name + "_embed");
    tensor->Reshape(slot.shape);
    tensor->SetLoD({slot.lod});
    ZeroCopyTensorAssignData<float>(tensor.get(), slot.data);
    inputs->emplace_back(std::move(tensor));
  }
}

// return the output values
std::vector<float> zerocopy_profile(int repeat_times) {
  AnalysisConfig config;
  SetConfig(&config);
  config.SwitchUseFeedFetchOps(false);
  auto predictor = CreatePaddlePredictor<AnalysisConfig>(config);
  std::vector<std::unique_ptr<ZeroCopyTensor>> inputs;
  PrepareZeroCopyInputs(predictor, &inputs);
  auto output_tensor = predictor->GetOutputTensor("reduce_sum_0.tmp_0");
  Timer timer;
  LOG(INFO) << "Warm up run...";
  timer.tic();
  predictor->ZeroCopyRun();
  PrintTime(FLAGS_batch_size, 1, 1, 0, timer.toc(), 1);
  if (FLAGS_profile) {
    paddle::platform::ResetProfiler();
  }
  LOG(INFO) << "Run " << repeat_times << " times...";
  timer.tic();
  for (int i = 0; i < repeat_times; i++) {
    predictor->ZeroCopyRun();
  }
  PrintTime(FLAGS_batch_size, repeat_times, 1, 0, timer.toc() / repeat_times,
            1);

  VLOG(3) << "ZeroCopy output: " << DescribeZeroCopyTensor(*output_tensor);
  PaddlePlace place;
  int output_size{0};
  auto *pdata = output_tensor->data<float>(&place, &output_size);
  std::vector<float> res(output_size);
  for (int i = 0; i < output_size; ++i) {
    res[i] = pdata[i];
  }
  return res;
}

TEST(Analyzer_seq_pool1, zerocopy_profile) { zerocopy_profile(FLAGS_repeat); }

TEST(Analyzer_seq_pool1, zerocopy_fuse_statis) { analysis_fuse_statis(true); }

TEST(Analyzer_seq_pool1, zerocopy_compare_native) {
  AnalysisConfig config;
  SetConfig(&config);
  config.SwitchUseFeedFetchOps(true);
  auto predictor = CreatePaddlePredictor<NativeConfig>(config.ToNativeConfig());
  std::vector<PaddleTensor> native_outputs;
  std::vector<std::vector<PaddleTensor>> input_slots_all;
  SetInput(&input_slots_all);
  ASSERT_TRUE(predictor->Run(input_slots_all[0], &native_outputs));
  EXPECT_EQ(native_outputs.size(), 1UL);

  auto zerocopy_output = zerocopy_profile(1);
  EXPECT_EQ(zerocopy_output.size() * sizeof(float),
            native_outputs.front().data.length());
  auto *native_data = static_cast<float *>(native_outputs.front().data.data());
  for (size_t i = 0; i < zerocopy_output.size(); ++i) {
    EXPECT_NEAR(zerocopy_output[i], native_data[i], 1e-3);
  }
}

}  // namespace analysis
}  // namespace inference
}  // namespace paddle
<commit_msg>add compare_determine of seqpool1 test<commit_after>/* Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */

#include <algorithm>
#include <fstream>
#include <iostream>
#include "paddle/fluid/inference/tests/api/tester_helper.h"

namespace paddle {
namespace inference {
namespace analysis {

struct OneSlotInBatch {
  std::string name;
  std::vector<std::vector<float>> data;
  std::vector<int> shape;
  std::vector<size_t> lod;
};

struct DataRecord {
  std::vector<std::vector<OneSlotInBatch>> batched_data;
  std::map<std::string, std::vector<std::vector<float>>> datasets;
  size_t batch_iter{0}, num_samples;  // total number of samples

  DataRecord() = default;
  explicit DataRecord(const std::string &path, int batch_size = 1) {
    Load(path);
    Prepare(batch_size);
  }

  void Load(const std::string &path) {
    std::ifstream file(path);
    constexpr int num_slots = 154;
    std::string line;
    int num_lines = 0;
    while (std::getline(file, line)) {
      num_lines++;
      std::vector<std::string> data;
      split(line, '\t', &data);
      std::vector<float> slot_data;
      split_to_float(data[1], ' ', &slot_data);
      std::string name = data[0];
      PADDLE_ENFORCE_EQ(slot_data.size() % 11, 0,
                        "line %d, %s should be divisible", num_lines, name);
      datasets[name].emplace_back(std::move(slot_data));
    }
    num_samples = num_lines / num_slots;
    PADDLE_ENFORCE_EQ(num_samples * num_slots, static_cast<size_t>(num_lines),
                      "num samples should be divisible");
    PADDLE_ENFORCE_GT(num_samples, 0);
  }

  void Prepare(int bs) {
    for (auto it = datasets.begin(); it != datasets.end(); ++it) {
      PADDLE_ENFORCE_EQ(it->second.size(), num_samples,
                        "size of each slot should be equal");
    }
    size_t num_batches = num_samples / bs;
    EXPECT_GT(num_batches, 0);
    batched_data.resize(num_batches);
    for (auto &one_batch : batched_data) {
      one_batch.resize(datasets.size());
      size_t i = 0;
      for (auto it = datasets.begin(); it != datasets.end(); ++it) {
        auto &slot = one_batch[i];
        slot.name = it->first;
        slot.data.resize(bs);
        slot.lod.resize(bs + 1);
        slot.lod[0] = 0;
        auto &lod = slot.lod;
        auto &datas = it->second;
        for (int k = 0; k < bs; ++k) {
          size_t id = k + batch_iter * bs;
          std::copy(datas[id].begin(), datas[id].end(),
                    std::back_inserter(slot.data[k]));
          size_t len = datas[id].size() / 11;
          PADDLE_ENFORCE_EQ(len * 11, datas[id].size(),
                            "%s %d size should be divisible", slot.name, id);
          lod[k + 1] = lod[k] + len;
        }
        slot.shape.assign({static_cast<int>(lod[bs]), 11});
        i++;
      }
    }
  }

  const std::vector<OneSlotInBatch> &NextBatch() {
    if (batch_iter >= batched_data.size() - 1) {
      batch_iter = -1;
    }
    return batched_data[++batch_iter];
  }
};

static void TensorAssignSlot(PaddleTensor *tensor, const OneSlotInBatch &slot) {
  tensor->name = slot.name + "_embed";
  tensor->shape = slot.shape;
  tensor->dtype = PaddleDType::FLOAT32;
  tensor->lod.clear();
  tensor->lod.emplace_back(slot.lod);
  TensorAssignData(tensor, slot.data);
}

void PrepareInputs(std::vector<PaddleTensor> *input_slots, DataRecord *data) {
  const auto &one_batch = data->NextBatch();
  input_slots->resize(one_batch.size());
  for (size_t i = 0; i < one_batch.size(); ++i) {
    auto &slot = one_batch[i];
    TensorAssignSlot(&((*input_slots)[i]), slot);
  }
}

void SetInput(std::vector<std::vector<PaddleTensor>> *inputs) {
  DataRecord data(FLAGS_infer_data, FLAGS_batch_size);
  std::vector<PaddleTensor> input_slots;
  int epoch = FLAGS_test_all_data ? data.batched_data.size() : 1;
  LOG(INFO) << "number of samples: "
            << data.batched_data.size() * FLAGS_batch_size;
  for (int bid = 0; bid < epoch; ++bid) {
    PrepareInputs(&input_slots, &data);
    (*inputs).emplace_back(input_slots);
  }
}

void SetConfig(AnalysisConfig *cfg, bool use_mkldnn = false) {
  cfg->SetModel(FLAGS_infer_model + "/model", FLAGS_infer_model + "/params");
  cfg->DisableGpu();
  cfg->SwitchSpecifyInputNames();
  cfg->pass_builder()->TurnOnDebug();
  cfg->SetCpuMathLibraryNumThreads(FLAGS_paddle_num_threads);
  if (use_mkldnn) {
    cfg->EnableMKLDNN();
  }
}

void profile(bool use_mkldnn = false) {
  AnalysisConfig cfg;
  SetConfig(&cfg, use_mkldnn);

  std::vector<PaddleTensor> outputs;
  std::vector<std::vector<PaddleTensor>> input_slots_all;
  SetInput(&input_slots_all);
  TestPrediction(reinterpret_cast<const PaddlePredictor::Config *>(&cfg),
                 input_slots_all, &outputs, FLAGS_num_threads);
}

TEST(Analyzer_seq_pool1, profile) { profile(); }

// Compare result of NativeConfig and AnalysisConfig
TEST(Analyzer_seq_pool1, compare) {
  AnalysisConfig cfg;
  SetConfig(&cfg);

  std::vector<std::vector<PaddleTensor>> input_slots_all;
  SetInput(&input_slots_all);
  CompareNativeAndAnalysis(
      reinterpret_cast<const PaddlePredictor::Config *>(&cfg), input_slots_all);
}

// Compare Deterministic result
TEST(Analyzer_seq_pool1, compare_determine) {
  AnalysisConfig cfg;
  SetConfig(&cfg);

  std::vector<std::vector<PaddleTensor>> input_slots_all;
  SetInput(&input_slots_all);
  CompareDeterministic(reinterpret_cast<const PaddlePredictor::Config *>(&cfg),
                       input_slots_all);
}

void analysis_fuse_statis(bool use_zerocopy) {
  AnalysisConfig cfg;
  SetConfig(&cfg);
  cfg.SwitchUseFeedFetchOps(!use_zerocopy);
  int num_ops;
  auto predictor = CreatePaddlePredictor<AnalysisConfig>(cfg);
  auto fuse_statis = GetFuseStatis(predictor.get(), &num_ops);
  ASSERT_TRUE(fuse_statis.count("fc_fuse"));
  ASSERT_EQ(fuse_statis.at("fc_fuse"), 10);
  ASSERT_TRUE(fuse_statis.count("seqpool_concat_fuse"));
  EXPECT_EQ(fuse_statis.at("seqpool_concat_fuse"), 2);
  LOG(INFO) << "num_ops: " << num_ops;
  EXPECT_EQ(num_ops, 195);
}

// Check the fuse status
TEST(Analyzer_seq_pool1, fuse_statis) { analysis_fuse_statis(false); }

void PrepareZeroCopyInputs(
    const std::unique_ptr<PaddlePredictor> &predictor,
    std::vector<std::unique_ptr<ZeroCopyTensor>> *inputs) {
  DataRecord data(FLAGS_infer_data, FLAGS_batch_size);
  // only feed one batch
  const auto &one_batch = data.NextBatch();
  inputs->clear();
  for (size_t i = 0; i < one_batch.size(); ++i) {
    auto &slot = one_batch[i];
    auto tensor = predictor->GetInputTensor(slot.name + "_embed");
    tensor->Reshape(slot.shape);
    tensor->SetLoD({slot.lod});
    ZeroCopyTensorAssignData<float>(tensor.get(), slot.data);
    inputs->emplace_back(std::move(tensor));
  }
}

// return the output values
std::vector<float> zerocopy_profile(int repeat_times) {
  AnalysisConfig config;
  SetConfig(&config);
  config.SwitchUseFeedFetchOps(false);
  auto predictor = CreatePaddlePredictor<AnalysisConfig>(config);
  std::vector<std::unique_ptr<ZeroCopyTensor>> inputs;
  PrepareZeroCopyInputs(predictor, &inputs);
  auto output_tensor = predictor->GetOutputTensor("reduce_sum_0.tmp_0");
  Timer timer;
  LOG(INFO) << "Warm up run...";
  timer.tic();
  predictor->ZeroCopyRun();
  PrintTime(FLAGS_batch_size, 1, 1, 0, timer.toc(), 1);
  if (FLAGS_profile) {
    paddle::platform::ResetProfiler();
  }
  LOG(INFO) << "Run " << repeat_times << " times...";
  timer.tic();
  for (int i = 0; i < repeat_times; i++) {
    predictor->ZeroCopyRun();
  }
  PrintTime(FLAGS_batch_size, repeat_times, 1, 0, timer.toc() / repeat_times,
            1);

  VLOG(3) << "ZeroCopy output: " << DescribeZeroCopyTensor(*output_tensor);
  PaddlePlace place;
  int output_size{0};
  auto *pdata = output_tensor->data<float>(&place, &output_size);
  std::vector<float> res(output_size);
  for (int i = 0; i < output_size; ++i) {
    res[i] = pdata[i];
  }
  return res;
}

TEST(Analyzer_seq_pool1, zerocopy_profile) { zerocopy_profile(FLAGS_repeat); }

TEST(Analyzer_seq_pool1, zerocopy_fuse_statis) { analysis_fuse_statis(true); }

TEST(Analyzer_seq_pool1, zerocopy_compare_native) {
  AnalysisConfig config;
  SetConfig(&config);
  config.SwitchUseFeedFetchOps(true);
  auto predictor = CreatePaddlePredictor<NativeConfig>(config.ToNativeConfig());
  std::vector<PaddleTensor> native_outputs;
  std::vector<std::vector<PaddleTensor>> input_slots_all;
  SetInput(&input_slots_all);
  ASSERT_TRUE(predictor->Run(input_slots_all[0], &native_outputs));
  EXPECT_EQ(native_outputs.size(), 1UL);

  auto zerocopy_output = zerocopy_profile(1);
  EXPECT_EQ(zerocopy_output.size() * sizeof(float),
            native_outputs.front().data.length());
  auto *native_data = static_cast<float *>(native_outputs.front().data.data());
  for (size_t i = 0; i < zerocopy_output.size(); ++i) {
    EXPECT_NEAR(zerocopy_output[i], native_data[i], 1e-3);
  }
}

}  // namespace analysis
}  // namespace inference
}  // namespace paddle
<|endoftext|>


<commit_before>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010 Francois Beaune
//
// 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.
//

// Interface header.
#include "diagnosticsurfaceshader.h"

// appleseed.renderer headers.
#include "renderer/kernel/shading/ambientocclusion.h"
#include "renderer/kernel/shading/shadingcontext.h"
#include "renderer/kernel/shading/shadingpoint.h"
#include "renderer/kernel/shading/shadingresult.h"
#include "renderer/modeling/camera/camera.h"
#include "renderer/modeling/input/inputarray.h"
#include "renderer/modeling/input/source.h"
#include "renderer/modeling/scene/scene.h"

// appleseed.foundation headers.
#include "foundation/image/colorspace.h"
#include "foundation/math/distance.h"
#include "foundation/math/hash.h"
#include "foundation/math/minmax.h"
#include "foundation/math/scalar.h"

using namespace foundation;
using namespace std;

namespace renderer
{

namespace
{
    // Utility function to compute a color from a given normal vector.
    inline void normal_to_color(const Vector3d& n, Spectrum& output)
    {
        assert(abs(n[0]) <= 1.0);
        assert(abs(n[1]) <= 1.0);
        assert(abs(n[2]) <= 1.0);

        output[0] = static_cast<float>((n[0] + 1.0) * 0.5);
        output[1] = static_cast<float>((n[1] + 1.0) * 0.5);
        output[2] = static_cast<float>((n[2] + 1.0) * 0.5);
    }

    // Utility function to compute a color from a given integer value.
    template <typename T>
    inline void integer_to_color(const T i, Spectrum& output)
    {
        const uint32 u = static_cast<uint32>(i);    // keep the low 32 bits

        const uint32 x = hashint32(u);
        const uint32 y = hashint32(u + 1);
        const uint32 z = hashint32(u + 2);

        output[0] = static_cast<float>(x) * (1.0f / 4294967295.0f);
        output[1] = static_cast<float>(y) * (1.0f / 4294967295.0f);
        output[2] = static_cast<float>(z) * (1.0f / 4294967295.0f);
    }
}

//
// Diagnostic surface shader.
//

struct DiagnosticSurfaceShader::Impl
{
    string                      m_name;
    ShadingMode                 m_shading_mode;
    double                      m_ao_max_distance;
    size_t                      m_ao_samples;
};

const KeyValuePair<const char*, DiagnosticSurfaceShader::ShadingMode>
    DiagnosticSurfaceShader::ShadingModeValues[] =
{
    { "coverage",               Coverage },
    { "barycentric",            Barycentric },
    { "uv",                     UV },
    { "geometric_normal",       GeometricNormal },
    { "shading_normal",         ShadingNormal },
    { "assembly_instances",     AssemblyInstances },
    { "object_instances",       ObjectInstances },
    { "regions",                Regions },
    { "triangles",              Triangles },
    { "materials",              Materials  },
    { "ambient_occlusion",      AmbientOcclusion },
    { "wireframe" ,             Wireframe }
};

const KeyValuePair<const char*, const char*> DiagnosticSurfaceShader::ShadingModeNames[] =
{
    { "coverage",               "Coverage" },
    { "barycentric",            "Barycentric Coordinates" },
    { "uv",                     "UV Coordinates" },
    { "geometric_normal",       "Geometric Normals" },
    { "shading_normal",         "Shading Normals" },
    { "assembly_instances",     "Assembly Instances" },
    { "object_instances",       "Object Instances" },
    { "regions",                "Regions" },
    { "triangles",              "Triangles" },
    { "materials",              "Materials" },
    { "ambient_occlusion",      "Ambient Occlusion" },
    { "wireframe" ,             "Wireframe" }
};

// Constructor.
DiagnosticSurfaceShader::DiagnosticSurfaceShader(
    const char*             name,
    const ParamArray&       params)
  : SurfaceShader(params)
  , impl(new Impl())
{
    impl->m_name = name;

    extract_parameters();
}

// Delete this instance.
void DiagnosticSurfaceShader::release()
{
    delete this;
}

// Return a string identifying the model of this surface shader.
const char* DiagnosticSurfaceShader::get_model() const
{
    return DiagnosticSurfaceShaderFactory::get_model();
}

// Return the name of this surface shader.
const char* DiagnosticSurfaceShader::get_name() const
{
    return impl->m_name.c_str();
}

// Evaluate the shading at a given point.
void DiagnosticSurfaceShader::evaluate(
    SamplingContext&        sampling_context,
    const ShadingContext&   shading_context,
    const ShadingPoint&     shading_point,
    ShadingResult&          shading_result) const
{
    // Set color space to linear RGB.
    shading_result.m_color_space = ColorSpaceLinearRGB;

    switch (impl->m_shading_mode)
    {
      // Shade according to pixel coverage
      case Coverage:
        shading_result.m_color[0] = 1.0f;
        shading_result.m_color[1] = 1.0f;
        shading_result.m_color[2] = 1.0f;
        break;

      // Shade according to barycentric coordinates.
      case Barycentric:
        {
            const Vector2d& bary = shading_point.get_bary();
            const double w = 1.0 - bary[0] - bary[1];
            shading_result.m_color[0] = static_cast<float>(w);
            shading_result.m_color[1] = static_cast<float>(bary[0]);
            shading_result.m_color[2] = static_cast<float>(bary[1]);
        }
        break;

      // Shade according to UV coordinates from UV set #0.
      case UV:
        {
            const Vector2d& uv0 = shading_point.get_uv(0);
            const double w = 1.0 - uv0[0] - uv0[1];
            shading_result.m_color[0] = static_cast<float>(w);
            shading_result.m_color[1] = static_cast<float>(uv0[0]);
            shading_result.m_color[2] = static_cast<float>(uv0[1]);
        }
        break;

      // Shade according to the geometric normal.
      case GeometricNormal:
        normal_to_color(
            shading_point.get_geometric_normal(),
            shading_result.m_color);
        break;

      // Shade according to the shading normal.
      case ShadingNormal:
        normal_to_color(
            shading_point.get_shading_normal(),
            shading_result.m_color);
        break;

      // Assign an unique color to each assembly instance.
      case AssemblyInstances:
        integer_to_color(
            shading_point.get_assembly_instance_uid(),
            shading_result.m_color);
        break;

      // Assign an unique color to each object instance.
      case ObjectInstances:
        {
            const uint32 h = mix32(
                static_cast<uint32>(shading_point.get_assembly_instance_uid()),
                static_cast<uint32>(shading_point.get_object_instance_index()));
            integer_to_color(h, shading_result.m_color);
        }
        break;

      // Assign an unique color to each region.
      case Regions:
        {
            const uint32 h = mix32(
                static_cast<uint32>(shading_point.get_assembly_instance_uid()),
                static_cast<uint32>(shading_point.get_object_instance_index()),
                static_cast<uint32>(shading_point.get_region_index()));
            integer_to_color(h, shading_result.m_color);
        }
        break;

      // Assign an unique color to each triangle.
      case Triangles:
        {
            const uint32 h = mix32(
                static_cast<uint32>(shading_point.get_assembly_instance_uid()),
                static_cast<uint32>(shading_point.get_object_instance_index()),
                static_cast<uint32>(shading_point.get_region_index()),
                static_cast<uint32>(shading_point.get_triangle_index()));
            integer_to_color(h, shading_result.m_color);
        }
        break;

      // Assign an unique color to each material.
      case Materials:
        {
            const ObjectInstance& object_instance = shading_point.get_object_instance();
            const MaterialIndexArray& material_indices = object_instance.get_material_indices();
            const size_t pa_index = shading_point.get_primitive_attribute_index();
            if (pa_index < material_indices.size())
            {
                const size_t material_index = material_indices[pa_index];
                const uint32 h = mix32(
                    static_cast<uint32>(shading_point.get_assembly_instance_uid()),
                    static_cast<uint32>(material_index));
                integer_to_color(h, shading_result.m_color);
            }
            else
            {
                shading_result.m_color[0] = 1.0f;
                shading_result.m_color[1] = 0.0f;
                shading_result.m_color[2] = 1.0f;
            }
        }
        break;

      // Ambient occlusion.
      case AmbientOcclusion:
        {
            // Compute the occlusion.
            const double occlusion =
                compute_ambient_occlusion(
                    sampling_context,
                    shading_context.get_intersector(),
                    shading_point.get_point(),
                    shading_point.get_geometric_normal(),
                    shading_point.get_shading_basis(),
                    impl->m_ao_max_distance,
                    impl->m_ao_samples,
                    &shading_point);

            // Return a gray scale value proportional to the accessibility.
            const float accessibility = static_cast<float>(1.0 - occlusion);
            shading_result.m_color[0] = accessibility;
            shading_result.m_color[1] = accessibility;
            shading_result.m_color[2] = accessibility;
        }
        break;

      // Wireframe.
      case Wireframe:
        {
            // Retrieve the camera.
            const Scene& scene = shading_point.get_scene();
            const Camera* camera = scene.get_camera();
            assert(camera);

            // Retrieve the camera transformation.
            const Transformd& camera_transform = camera->get_transform();

            // Retrieve world space triangle vertices.
            const Vector3d& v0 = shading_point.get_vertex(0);
            const Vector3d& v1 = shading_point.get_vertex(1);
            const Vector3d& v2 = shading_point.get_vertex(2);

            // Transform triangle vertices to camera space.
            const Vector3d v0_cs = camera_transform.transform_point_to_local(v0);
            const Vector3d v1_cs = camera_transform.transform_point_to_local(v1);
            const Vector3d v2_cs = camera_transform.transform_point_to_local(v2);

            // Project triangle vertices to film space.
            const Vector2d v0_fs = camera->project(v0_cs);
            const Vector2d v1_fs = camera->project(v1_cs);
            const Vector2d v2_fs = camera->project(v2_cs);

            // Retrieve world space intersection point.
            const Vector3d& point = shading_point.get_point();

            // Transform intersection point to camera space.
            const Vector3d point_cs = camera_transform.transform_point_to_local(point);

            // Project intersection point to film space.
            const Vector2d point_fs = camera->project(point_cs);

            // Compute film space distance from intersection point to triangle edges.
            const double d0 = square_distance_point_segment(point_fs, v0_fs, v1_fs);
            const double d1 = square_distance_point_segment(point_fs, v1_fs, v2_fs);
            const double d2 = square_distance_point_segment(point_fs, v2_fs, v0_fs);

            // Film space thickness of the wires.
            const double SquareWireThickness = square(0.002);

            if (min(d0, d1, d2) < SquareWireThickness)
            {
                shading_result.m_color[0] = 1.0f;
                shading_result.m_color[1] = 1.0f;
                shading_result.m_color[2] = 1.0f;
            }
            else
            {
                shading_result.m_color[0] = 0.0f;
                shading_result.m_color[1] = 0.0f;
                shading_result.m_color[2] = 0.8f;
            }
        }
        break;

      // Invalid shader.
      default:
        assert(false);
        shading_result.m_color[0] = 1.0f;
        shading_result.m_color[1] = 0.0f;
        shading_result.m_color[2] = 1.0f;
        break;
    }

    // Set alpha channel to full opacity.
    shading_result.m_alpha = Alpha(1.0);
}

void DiagnosticSurfaceShader::extract_parameters()
{
    // Retrieve shading mode.
    const string mode_string = m_params.get_required<string>("mode", "coverage");
    const KeyValuePair<const char*, ShadingMode>* mode_pair =
        lookup_kvpair_array(ShadingModeValues, ShadingModeCount, mode_string);
    if (mode_pair)
    {
        impl->m_shading_mode = mode_pair->m_value;
    }
    else
    {
        RENDERER_LOG_ERROR(
            "invalid shading mode \"%s\", using default value \"coverage\"",
            mode_string.c_str());
        impl->m_shading_mode = Coverage;
    }

    // Retrieve ambient occlusion parameters.
    if (impl->m_shading_mode == AmbientOcclusion)
    {
        const ParamArray& ao_params = m_params.child("ambient_occlusion");
        impl->m_ao_max_distance = ao_params.get_required<double>("max_distance", 1.0);
        impl->m_ao_samples = ao_params.get_required<size_t>("samples", 16);
    }
}

//
// DiagnosticSurfaceShaderFactory class implementation.
//

// Return a string identifying this surface shader model.
const char* DiagnosticSurfaceShaderFactory::get_model()
{
    return "diagnostic_surface_shader";
}

// Create a new diagnostic surface shader.
auto_release_ptr<SurfaceShader> DiagnosticSurfaceShaderFactory::create(
    const char*         name,
    const ParamArray&   params)
{
    return
        auto_release_ptr<SurfaceShader>(
            new DiagnosticSurfaceShader(name, params));
}

}   // namespace renderer
<commit_msg>decreased the thickness of the wires in the "wireframe" mode of the diagnostic shader.<commit_after>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010 Francois Beaune
//
// 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.
//

// Interface header.
#include "diagnosticsurfaceshader.h"

// appleseed.renderer headers.
#include "renderer/kernel/shading/ambientocclusion.h"
#include "renderer/kernel/shading/shadingcontext.h"
#include "renderer/kernel/shading/shadingpoint.h"
#include "renderer/kernel/shading/shadingresult.h"
#include "renderer/modeling/camera/camera.h"
#include "renderer/modeling/input/inputarray.h"
#include "renderer/modeling/input/source.h"
#include "renderer/modeling/scene/scene.h"

// appleseed.foundation headers.
#include "foundation/image/colorspace.h"
#include "foundation/math/distance.h"
#include "foundation/math/hash.h"
#include "foundation/math/minmax.h"
#include "foundation/math/scalar.h"

using namespace foundation;
using namespace std;

namespace renderer
{

namespace
{
    // Utility function to compute a color from a given normal vector.
    inline void normal_to_color(const Vector3d& n, Spectrum& output)
    {
        assert(abs(n[0]) <= 1.0);
        assert(abs(n[1]) <= 1.0);
        assert(abs(n[2]) <= 1.0);

        output[0] = static_cast<float>((n[0] + 1.0) * 0.5);
        output[1] = static_cast<float>((n[1] + 1.0) * 0.5);
        output[2] = static_cast<float>((n[2] + 1.0) * 0.5);
    }

    // Utility function to compute a color from a given integer value.
    template <typename T>
    inline void integer_to_color(const T i, Spectrum& output)
    {
        const uint32 u = static_cast<uint32>(i);    // keep the low 32 bits

        const uint32 x = hashint32(u);
        const uint32 y = hashint32(u + 1);
        const uint32 z = hashint32(u + 2);

        output[0] = static_cast<float>(x) * (1.0f / 4294967295.0f);
        output[1] = static_cast<float>(y) * (1.0f / 4294967295.0f);
        output[2] = static_cast<float>(z) * (1.0f / 4294967295.0f);
    }
}

//
// Diagnostic surface shader.
//

struct DiagnosticSurfaceShader::Impl
{
    string                      m_name;
    ShadingMode                 m_shading_mode;
    double                      m_ao_max_distance;
    size_t                      m_ao_samples;
};

const KeyValuePair<const char*, DiagnosticSurfaceShader::ShadingMode>
    DiagnosticSurfaceShader::ShadingModeValues[] =
{
    { "coverage",               Coverage },
    { "barycentric",            Barycentric },
    { "uv",                     UV },
    { "geometric_normal",       GeometricNormal },
    { "shading_normal",         ShadingNormal },
    { "assembly_instances",     AssemblyInstances },
    { "object_instances",       ObjectInstances },
    { "regions",                Regions },
    { "triangles",              Triangles },
    { "materials",              Materials  },
    { "ambient_occlusion",      AmbientOcclusion },
    { "wireframe" ,             Wireframe }
};

const KeyValuePair<const char*, const char*> DiagnosticSurfaceShader::ShadingModeNames[] =
{
    { "coverage",               "Coverage" },
    { "barycentric",            "Barycentric Coordinates" },
    { "uv",                     "UV Coordinates" },
    { "geometric_normal",       "Geometric Normals" },
    { "shading_normal",         "Shading Normals" },
    { "assembly_instances",     "Assembly Instances" },
    { "object_instances",       "Object Instances" },
    { "regions",                "Regions" },
    { "triangles",              "Triangles" },
    { "materials",              "Materials" },
    { "ambient_occlusion",      "Ambient Occlusion" },
    { "wireframe" ,             "Wireframe" }
};

// Constructor.
DiagnosticSurfaceShader::DiagnosticSurfaceShader(
    const char*             name,
    const ParamArray&       params)
  : SurfaceShader(params)
  , impl(new Impl())
{
    impl->m_name = name;

    extract_parameters();
}

// Delete this instance.
void DiagnosticSurfaceShader::release()
{
    delete this;
}

// Return a string identifying the model of this surface shader.
const char* DiagnosticSurfaceShader::get_model() const
{
    return DiagnosticSurfaceShaderFactory::get_model();
}

// Return the name of this surface shader.
const char* DiagnosticSurfaceShader::get_name() const
{
    return impl->m_name.c_str();
}

// Evaluate the shading at a given point.
void DiagnosticSurfaceShader::evaluate(
    SamplingContext&        sampling_context,
    const ShadingContext&   shading_context,
    const ShadingPoint&     shading_point,
    ShadingResult&          shading_result) const
{
    // Set color space to linear RGB.
    shading_result.m_color_space = ColorSpaceLinearRGB;

    switch (impl->m_shading_mode)
    {
      // Shade according to pixel coverage
      case Coverage:
        shading_result.m_color[0] = 1.0f;
        shading_result.m_color[1] = 1.0f;
        shading_result.m_color[2] = 1.0f;
        break;

      // Shade according to barycentric coordinates.
      case Barycentric:
        {
            const Vector2d& bary = shading_point.get_bary();
            const double w = 1.0 - bary[0] - bary[1];
            shading_result.m_color[0] = static_cast<float>(w);
            shading_result.m_color[1] = static_cast<float>(bary[0]);
            shading_result.m_color[2] = static_cast<float>(bary[1]);
        }
        break;

      // Shade according to UV coordinates from UV set #0.
      case UV:
        {
            const Vector2d& uv0 = shading_point.get_uv(0);
            const double w = 1.0 - uv0[0] - uv0[1];
            shading_result.m_color[0] = static_cast<float>(w);
            shading_result.m_color[1] = static_cast<float>(uv0[0]);
            shading_result.m_color[2] = static_cast<float>(uv0[1]);
        }
        break;

      // Shade according to the geometric normal.
      case GeometricNormal:
        normal_to_color(
            shading_point.get_geometric_normal(),
            shading_result.m_color);
        break;

      // Shade according to the shading normal.
      case ShadingNormal:
        normal_to_color(
            shading_point.get_shading_normal(),
            shading_result.m_color);
        break;

      // Assign an unique color to each assembly instance.
      case AssemblyInstances:
        integer_to_color(
            shading_point.get_assembly_instance_uid(),
            shading_result.m_color);
        break;

      // Assign an unique color to each object instance.
      case ObjectInstances:
        {
            const uint32 h = mix32(
                static_cast<uint32>(shading_point.get_assembly_instance_uid()),
                static_cast<uint32>(shading_point.get_object_instance_index()));
            integer_to_color(h, shading_result.m_color);
        }
        break;

      // Assign an unique color to each region.
      case Regions:
        {
            const uint32 h = mix32(
                static_cast<uint32>(shading_point.get_assembly_instance_uid()),
                static_cast<uint32>(shading_point.get_object_instance_index()),
                static_cast<uint32>(shading_point.get_region_index()));
            integer_to_color(h, shading_result.m_color);
        }
        break;

      // Assign an unique color to each triangle.
      case Triangles:
        {
            const uint32 h = mix32(
                static_cast<uint32>(shading_point.get_assembly_instance_uid()),
                static_cast<uint32>(shading_point.get_object_instance_index()),
                static_cast<uint32>(shading_point.get_region_index()),
                static_cast<uint32>(shading_point.get_triangle_index()));
            integer_to_color(h, shading_result.m_color);
        }
        break;

      // Assign an unique color to each material.
      case Materials:
        {
            const ObjectInstance& object_instance = shading_point.get_object_instance();
            const MaterialIndexArray& material_indices = object_instance.get_material_indices();
            const size_t pa_index = shading_point.get_primitive_attribute_index();
            if (pa_index < material_indices.size())
            {
                const size_t material_index = material_indices[pa_index];
                const uint32 h = mix32(
                    static_cast<uint32>(shading_point.get_assembly_instance_uid()),
                    static_cast<uint32>(material_index));
                integer_to_color(h, shading_result.m_color);
            }
            else
            {
                shading_result.m_color[0] = 1.0f;
                shading_result.m_color[1] = 0.0f;
                shading_result.m_color[2] = 1.0f;
            }
        }
        break;

      // Ambient occlusion.
      case AmbientOcclusion:
        {
            // Compute the occlusion.
            const double occlusion =
                compute_ambient_occlusion(
                    sampling_context,
                    shading_context.get_intersector(),
                    shading_point.get_point(),
                    shading_point.get_geometric_normal(),
                    shading_point.get_shading_basis(),
                    impl->m_ao_max_distance,
                    impl->m_ao_samples,
                    &shading_point);

            // Return a gray scale value proportional to the accessibility.
            const float accessibility = static_cast<float>(1.0 - occlusion);
            shading_result.m_color[0] = accessibility;
            shading_result.m_color[1] = accessibility;
            shading_result.m_color[2] = accessibility;
        }
        break;

      // Wireframe.
      case Wireframe:
        {
            // Retrieve the camera.
            const Scene& scene = shading_point.get_scene();
            const Camera* camera = scene.get_camera();
            assert(camera);

            // Retrieve the camera transformation.
            const Transformd& camera_transform = camera->get_transform();

            // Retrieve world space triangle vertices.
            const Vector3d& v0 = shading_point.get_vertex(0);
            const Vector3d& v1 = shading_point.get_vertex(1);
            const Vector3d& v2 = shading_point.get_vertex(2);

            // Transform triangle vertices to camera space.
            const Vector3d v0_cs = camera_transform.transform_point_to_local(v0);
            const Vector3d v1_cs = camera_transform.transform_point_to_local(v1);
            const Vector3d v2_cs = camera_transform.transform_point_to_local(v2);

            // Project triangle vertices to film space.
            const Vector2d v0_fs = camera->project(v0_cs);
            const Vector2d v1_fs = camera->project(v1_cs);
            const Vector2d v2_fs = camera->project(v2_cs);

            // Retrieve world space intersection point.
            const Vector3d& point = shading_point.get_point();

            // Transform intersection point to camera space.
            const Vector3d point_cs = camera_transform.transform_point_to_local(point);

            // Project intersection point to film space.
            const Vector2d point_fs = camera->project(point_cs);

            // Compute film space distance from intersection point to triangle edges.
            const double d0 = square_distance_point_segment(point_fs, v0_fs, v1_fs);
            const double d1 = square_distance_point_segment(point_fs, v1_fs, v2_fs);
            const double d2 = square_distance_point_segment(point_fs, v2_fs, v0_fs);

            // Film space thickness of the wires.
            const double SquareWireThickness = square(0.0005);

            if (min(d0, d1, d2) < SquareWireThickness)
            {
                shading_result.m_color[0] = 1.0f;
                shading_result.m_color[1] = 1.0f;
                shading_result.m_color[2] = 1.0f;
            }
            else
            {
                shading_result.m_color[0] = 0.0f;
                shading_result.m_color[1] = 0.0f;
                shading_result.m_color[2] = 0.8f;
            }
        }
        break;

      // Invalid shader.
      default:
        assert(false);
        shading_result.m_color[0] = 1.0f;
        shading_result.m_color[1] = 0.0f;
        shading_result.m_color[2] = 1.0f;
        break;
    }

    // Set alpha channel to full opacity.
    shading_result.m_alpha = Alpha(1.0);
}

void DiagnosticSurfaceShader::extract_parameters()
{
    // Retrieve shading mode.
    const string mode_string = m_params.get_required<string>("mode", "coverage");
    const KeyValuePair<const char*, ShadingMode>* mode_pair =
        lookup_kvpair_array(ShadingModeValues, ShadingModeCount, mode_string);
    if (mode_pair)
    {
        impl->m_shading_mode = mode_pair->m_value;
    }
    else
    {
        RENDERER_LOG_ERROR(
            "invalid shading mode \"%s\", using default value \"coverage\"",
            mode_string.c_str());
        impl->m_shading_mode = Coverage;
    }

    // Retrieve ambient occlusion parameters.
    if (impl->m_shading_mode == AmbientOcclusion)
    {
        const ParamArray& ao_params = m_params.child("ambient_occlusion");
        impl->m_ao_max_distance = ao_params.get_required<double>("max_distance", 1.0);
        impl->m_ao_samples = ao_params.get_required<size_t>("samples", 16);
    }
}

//
// DiagnosticSurfaceShaderFactory class implementation.
//

// Return a string identifying this surface shader model.
const char* DiagnosticSurfaceShaderFactory::get_model()
{
    return "diagnostic_surface_shader";
}

// Create a new diagnostic surface shader.
auto_release_ptr<SurfaceShader> DiagnosticSurfaceShaderFactory::create(
    const char*         name,
    const ParamArray&   params)
{
    return
        auto_release_ptr<SurfaceShader>(
            new DiagnosticSurfaceShader(name, params));
}

}   // namespace renderer
<|endoftext|>


<commit_before>#define GUILITE_ON  //Do not define this macro once more!!!
#include "GuiLite.h"

#define UI_WIDTH 240
#define UI_HEIGHT 320

#define LAYER_1_X 70
#define LAYER_1_Y 110
#define LAYER_1_WIDTH  100
#define LAYER_1_HEIGHT 80

static c_surface* s_surface;
static c_display* s_display;

//////////////////////// start UI ////////////////////////

void draw_on_layer_0()
{
	s_surface->fill_rect(0, 0, UI_WIDTH - 1, UI_HEIGHT - 1, 0, Z_ORDER_LEVEL_0);
	c_word::draw_string(s_surface, Z_ORDER_LEVEL_0, "layer 0: the bottom", 30, LAYER_1_Y + 30, c_theme::get_font(FONT_DEFAULT), GL_RGB(255, 255, 255), GL_ARGB(0, 0, 0, 0));
}

void draw_on_layer_1()
{
	s_surface->fill_rect(LAYER_1_X, LAYER_1_Y, LAYER_1_X + LAYER_1_WIDTH - 1, LAYER_1_Y + LAYER_1_HEIGHT - 1, GL_RGB(69, 75, 91), Z_ORDER_LEVEL_1);
	c_word::draw_string(s_surface, Z_ORDER_LEVEL_1, "layer 1:", LAYER_1_X + 10, LAYER_1_Y + 19, c_theme::get_font(FONT_DEFAULT), GL_RGB(255, 255, 255), GL_RGB(69, 75, 91));
	c_word::draw_string(s_surface, Z_ORDER_LEVEL_1, "the top", LAYER_1_X + 10, LAYER_1_Y + 38, c_theme::get_font(FONT_DEFAULT), GL_RGB(255, 255, 255), GL_RGB(69, 75, 91));
}

void clear_layer_1()
{
#if 0
	//no animation
	c_rect overlapped_rect(LAYER_1_X, LAYER_1_Y, LAYER_1_X + LAYER_1_WIDTH - 1, LAYER_1_Y + LAYER_1_HEIGHT - 1);
	s_surface->show_overlapped_rect(overlapped_rect, Z_ORDER_LEVEL_0);
#else
	//animation
	for (int offset = 0; offset < LAYER_1_HEIGHT / 2; offset++)
	{
		c_rect overlapped_rect_top(LAYER_1_X, LAYER_1_Y + offset, LAYER_1_X + LAYER_1_WIDTH - 1, LAYER_1_Y + offset + 1);
		s_surface->show_overlapped_rect(overlapped_rect_top, Z_ORDER_LEVEL_0);

		c_rect overlapped_rect_bottom(LAYER_1_X, LAYER_1_Y + LAYER_1_HEIGHT - offset - 2, LAYER_1_X + LAYER_1_WIDTH - 1, LAYER_1_Y + LAYER_1_HEIGHT - offset - 1);
		s_surface->show_overlapped_rect(overlapped_rect_bottom, Z_ORDER_LEVEL_0);

		thread_sleep(5);
	}
#endif
}

extern const FONT_INFO Consolas_19;
void load_resource()
{
	c_theme::add_font(FONT_DEFAULT, &Consolas_19);
}

void create_ui(void* phy_fb, int screen_width, int screen_height, int color_bytes, struct EXTERNAL_GFX_OP* gfx_op) {
	if (phy_fb)
	{
		static c_surface surface(UI_WIDTH, UI_HEIGHT, color_bytes, Z_ORDER_LEVEL_1, c_rect(LAYER_1_X, LAYER_1_Y, LAYER_1_X + LAYER_1_WIDTH - 1, LAYER_1_Y + LAYER_1_HEIGHT - 1));
		static c_display display(phy_fb, screen_width, screen_height, &surface);
		s_surface = &surface;
		s_display = &display;
	}
	else
	{//for MCU without framebuffer
		static c_surface_no_fb surface_no_fb(UI_WIDTH, UI_HEIGHT, color_bytes, gfx_op, Z_ORDER_LEVEL_1, c_rect(LAYER_1_X, LAYER_1_Y, LAYER_1_X + LAYER_1_WIDTH - 1, LAYER_1_Y + LAYER_1_HEIGHT - 1));
		static c_display display(phy_fb, screen_width, screen_height, &surface_no_fb);
		s_surface = &surface_no_fb;
		s_display = &display;
	}

	load_resource();
	draw_on_layer_0();
	while(1) {
		draw_on_layer_1();
		thread_sleep(3000);
		clear_layer_1();
		thread_sleep(3000);
	}
}

//////////////////////// interface for all platform ////////////////////////
extern "C" void startHelloLayers(void* phy_fb, int width, int height, int color_bytes, struct EXTERNAL_GFX_OP* gfx_op) {
	create_ui(phy_fb, width, height, color_bytes, gfx_op);
}

void* getUiOfHelloLayers(int* width, int* height, bool force_update)
{
	if (s_display)
	{
		return s_display->get_updated_fb(width, height, force_update);
	}
	return NULL;
}
<commit_msg>add shutter effect for helloLayers<commit_after>#define GUILITE_ON  //Do not define this macro once more!!!
#include "GuiLite.h"

#define UI_WIDTH 240
#define UI_HEIGHT 320

#define LAYER_1_X 70
#define LAYER_1_Y 110

#define SHADES_CNT 10
#define SHADE_HEIGHT 10
#define LAYER_1_WIDTH  80
#define LAYER_1_HEIGHT SHADES_CNT * SHADE_HEIGHT

static c_surface* s_surface;
static c_display* s_display;

//////////////////////// start UI ////////////////////////

void draw_on_layer_0()
{
	s_surface->fill_rect(0, 0, UI_WIDTH - 1, UI_HEIGHT - 1, 0, Z_ORDER_LEVEL_0);
	c_word::draw_string(s_surface, Z_ORDER_LEVEL_0, "layer 0: the bottom", 30, LAYER_1_Y + 30, c_theme::get_font(FONT_DEFAULT), GL_RGB(255, 255, 255), GL_ARGB(0, 0, 0, 0));
}

void draw_on_layer_1()
{
	s_surface->fill_rect(LAYER_1_X, LAYER_1_Y, LAYER_1_X + LAYER_1_WIDTH - 1, LAYER_1_Y + LAYER_1_HEIGHT - 1, GL_RGB(0, 122, 204), Z_ORDER_LEVEL_1);
	c_word::draw_string(s_surface, Z_ORDER_LEVEL_1, "layer 1:", LAYER_1_X + 5, LAYER_1_Y + 19, c_theme::get_font(FONT_DEFAULT), GL_RGB(255, 255, 255), GL_RGB(0, 122, 204));
	c_word::draw_string(s_surface, Z_ORDER_LEVEL_1, "the top", LAYER_1_X + 5, LAYER_1_Y + 38, c_theme::get_font(FONT_DEFAULT), GL_RGB(255, 255, 255), GL_RGB(0, 122, 204));
}

void clear_layer_1()
{
#if 0
	//no animation
	c_rect overlapped_rect(LAYER_1_X, LAYER_1_Y, LAYER_1_X + LAYER_1_WIDTH - 1, LAYER_1_Y + LAYER_1_HEIGHT - 1);
	s_surface->show_overlapped_rect(overlapped_rect, Z_ORDER_LEVEL_0);
#else
	//animation
	for (int offset = 0; offset < SHADE_HEIGHT; offset++)
	{
		for (int i = 0; i < SHADES_CNT; i++)
		{
			c_rect overlapped_rect_top(LAYER_1_X, LAYER_1_Y + (SHADE_HEIGHT * i) + offset, LAYER_1_X + LAYER_1_WIDTH - 1, LAYER_1_Y + (SHADE_HEIGHT * i) + offset);
			s_surface->show_overlapped_rect(overlapped_rect_top, Z_ORDER_LEVEL_0);
		}
		thread_sleep(5);
	}
#endif
}

extern const FONT_INFO Consolas_19;
void load_resource()
{
	c_theme::add_font(FONT_DEFAULT, &Consolas_19);
}

void create_ui(void* phy_fb, int screen_width, int screen_height, int color_bytes, struct EXTERNAL_GFX_OP* gfx_op) {
	if (phy_fb)
	{
		static c_surface surface(UI_WIDTH, UI_HEIGHT, color_bytes, Z_ORDER_LEVEL_1, c_rect(LAYER_1_X, LAYER_1_Y, LAYER_1_X + LAYER_1_WIDTH - 1, LAYER_1_Y + LAYER_1_HEIGHT - 1));
		static c_display display(phy_fb, screen_width, screen_height, &surface);
		s_surface = &surface;
		s_display = &display;
	}
	else
	{//for MCU without framebuffer
		static c_surface_no_fb surface_no_fb(UI_WIDTH, UI_HEIGHT, color_bytes, gfx_op, Z_ORDER_LEVEL_1, c_rect(LAYER_1_X, LAYER_1_Y, LAYER_1_X + LAYER_1_WIDTH - 1, LAYER_1_Y + LAYER_1_HEIGHT - 1));
		static c_display display(phy_fb, screen_width, screen_height, &surface_no_fb);
		s_surface = &surface_no_fb;
		s_display = &display;
	}

	load_resource();
	draw_on_layer_0();
	while(1) {
		draw_on_layer_1();
		thread_sleep(3000);
		clear_layer_1();
		thread_sleep(3000);
	}
}

//////////////////////// interface for all platform ////////////////////////
extern "C" void startHelloLayers(void* phy_fb, int width, int height, int color_bytes, struct EXTERNAL_GFX_OP* gfx_op) {
	create_ui(phy_fb, width, height, color_bytes, gfx_op);
}

void* getUiOfHelloLayers(int* width, int* height, bool force_update)
{
	if (s_display)
	{
		return s_display->get_updated_fb(width, height, force_update);
	}
	return NULL;
}
<|endoftext|>


<commit_before>/*
   The MIT License

   Copyright (c) 2009 Institut of Mechanics and Fluid Dynamics,
   TU Bergakademie Freiberg.

   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    REKConverter.cpp
  \author  Andre Liebscher
           Institut of Mechanics and Fluid Dynamics
           TU Bergakademie Freiberg
  \date    March 2009
*/

#include <fstream>
#include <sstream>
#include <cstring>
#include "REKConverter.h"
#include "Controller/Controller.h"
#include "boost/cstdint.hpp"

using namespace std;

REKConverter::REKConverter()
{
  m_vConverterDesc = "Fraunhofer EZRT Volume";
  m_vSupportedExt.push_back("REK");
}

bool
REKConverter::ConvertToRAW(const std::string& strSourceFilename,
                                  const std::string&,
                                  bool, UINT64& iHeaderSkip,
                                  UINT64& iComponentSize,
                                  UINT64& iComponentCount,
                                  bool& bConvertEndianess, bool& bSigned,
                                  bool& bIsFloat, UINTVECTOR3& vVolumeSize,
                                  FLOATVECTOR3& vVolumeAspect,
                                  std::string& strTitle,
                                  UVFTables::ElementSemanticTable& eType,
                                  std::string& strIntermediateFile,
                                  bool& bDeleteIntermediateFile)
{
  MESSAGE("Attempting to convert REK dataset %s", strSourceFilename.c_str());

  // Read header an check for "magic" values of the REK file
  ifstream fileData(strSourceFilename.c_str(), ifstream::in | ifstream::binary);
  char buffer[2048];

  if(fileData.is_open()) {
    fileData.read( buffer, sizeof(buffer) );
    char ff[] = { 255, 255, 255, 255 };
    if( memcmp(&buffer[116], &ff, 4) != 0 ) {
      WARNING("The file %s is not a REK file", strSourceFilename.c_str());
      fileData.close();
      return false;
    }
  } else {
    WARNING("Could not open REK file %s", strSourceFilename.c_str());
    return false;
  }
  fileData.close();

  // standard values which are always true (I guess)
  strTitle = "Fraunhofer EZRT";
  eType = UVFTables::ES_UNDEFINED;
  vVolumeAspect = FLOATVECTOR3(1,1,1);
  bSigned = false;
  bIsFloat = false;
  iComponentCount = 1;
  strIntermediateFile = strSourceFilename;
  bDeleteIntermediateFile = false;

  // read file format from header - first try to guess endieness from offset 4-5 (bits per pixel)
  // Anyway, I do not think that anyone would ever encounter such a file stored in big endian encoding.
  bConvertEndianess = Parse<boost::uint16_t, 2>( &buffer[4] ) > 32;

  vVolumeSize[0] = Parse<boost::uint16_t, 2>( &buffer[0], bConvertEndianess );
  vVolumeSize[1] = Parse<boost::uint16_t, 2>( &buffer[2], bConvertEndianess );
  vVolumeSize[2] = Parse<boost::uint16_t, 2>( &buffer[6], bConvertEndianess );
  iComponentSize = Parse<boost::uint16_t, 2>( &buffer[4], bConvertEndianess );
  iHeaderSkip = Parse<boost::uint16_t, 2>( &buffer[8], bConvertEndianess );

  return true;
}

// unimplemented!
bool
REKConverter::ConvertToNative(const std::string&,
                                     const std::string&,
                                     UINT64, UINT64,
                                     UINT64, bool,
                                     bool,
                                     UINTVECTOR3,
                                     FLOATVECTOR3,
                                     bool)
{
  return false;
}
<commit_msg>Fix a warning on windows.<commit_after>/*
   The MIT License

   Copyright (c) 2009 Institut of Mechanics and Fluid Dynamics,
   TU Bergakademie Freiberg.

   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    REKConverter.cpp
  \author  Andre Liebscher
           Institut of Mechanics and Fluid Dynamics
           TU Bergakademie Freiberg
  \date    March 2009
*/

#include <fstream>
#include <sstream>
#include <cstring>
#include "REKConverter.h"
#include "Controller/Controller.h"
#include "boost/cstdint.hpp"

using namespace std;

REKConverter::REKConverter()
{
  m_vConverterDesc = "Fraunhofer EZRT Volume";
  m_vSupportedExt.push_back("REK");
}

bool
REKConverter::ConvertToRAW(const std::string& strSourceFilename,
                                  const std::string&,
                                  bool, UINT64& iHeaderSkip,
                                  UINT64& iComponentSize,
                                  UINT64& iComponentCount,
                                  bool& bConvertEndianess, bool& bSigned,
                                  bool& bIsFloat, UINTVECTOR3& vVolumeSize,
                                  FLOATVECTOR3& vVolumeAspect,
                                  std::string& strTitle,
                                  UVFTables::ElementSemanticTable& eType,
                                  std::string& strIntermediateFile,
                                  bool& bDeleteIntermediateFile)
{
  MESSAGE("Attempting to convert REK dataset %s", strSourceFilename.c_str());

  // Read header an check for "magic" values of the REK file
  ifstream fileData(strSourceFilename.c_str(), ifstream::in | ifstream::binary);
  char buffer[2048];

  if(fileData.is_open()) {
    fileData.read( buffer, sizeof(buffer) );
    unsigned char ff[] = { 255, 255, 255, 255 };
    if( memcmp(&buffer[116], &ff, 4) != 0 ) {
      WARNING("The file %s is not a REK file", strSourceFilename.c_str());
      fileData.close();
      return false;
    }
  } else {
    WARNING("Could not open REK file %s", strSourceFilename.c_str());
    return false;
  }
  fileData.close();

  // standard values which are always true (I guess)
  strTitle = "Fraunhofer EZRT";
  eType = UVFTables::ES_UNDEFINED;
  vVolumeAspect = FLOATVECTOR3(1,1,1);
  bSigned = false;
  bIsFloat = false;
  iComponentCount = 1;
  strIntermediateFile = strSourceFilename;
  bDeleteIntermediateFile = false;

  // read file format from header - first try to guess endieness from offset 4-5 (bits per pixel)
  // Anyway, I do not think that anyone would ever encounter such a file stored in big endian encoding.
  bConvertEndianess = Parse<boost::uint16_t, 2>( &buffer[4] ) > 32;

  vVolumeSize[0] = Parse<boost::uint16_t, 2>( &buffer[0], bConvertEndianess );
  vVolumeSize[1] = Parse<boost::uint16_t, 2>( &buffer[2], bConvertEndianess );
  vVolumeSize[2] = Parse<boost::uint16_t, 2>( &buffer[6], bConvertEndianess );
  iComponentSize = Parse<boost::uint16_t, 2>( &buffer[4], bConvertEndianess );
  iHeaderSkip = Parse<boost::uint16_t, 2>( &buffer[8], bConvertEndianess );

  return true;
}

// unimplemented!
bool
REKConverter::ConvertToNative(const std::string&,
                                     const std::string&,
                                     UINT64, UINT64,
                                     UINT64, bool,
                                     bool,
                                     UINTVECTOR3,
                                     FLOATVECTOR3,
                                     bool)
{
  return false;
}
<|endoftext|>