<commit_before>#ifndef H_EXTENSIONS_CUTEHMI_TEST_0_INCLUDE_CUTEHMI_TEST_RANDOM_HPP
#define H_EXTENSIONS_CUTEHMI_TEST_0_INCLUDE_CUTEHMI_TEST_RANDOM_HPP

#include "IsIntType.hpp"

#include <QChar>
#include <QString>
#include <QList>
#include <QMultiHash>

#include <random>
#include <chrono>
#include <limits>
#include <type_traits>

namespace cutehmi {
namespace test {

/**
 * Seeded engine. This class extends random generator class specified by @a E
 * template parameter and behaves exactly like extended class, except it seeds
 * itself within a constructor.
 * @tparam E random number generator engine.
 */
template <class E = std::mt19937>
class SeededEngine:
	public E
{
	public:
		/**
		 * Default constructor.
		 */
		SeededEngine();
};

template <class E>
SeededEngine<E>::SeededEngine()
{
	std::random_device randomDevice;

	// Some implementations do not have non-deterministic std::random_device.
	// Check out entropy of std::random_device. If it's zero, then fallback to
	// time-based seed.
	//
	// Note that sometimes it's std::random_device::entropy(), which is not
	// implemented properly, accodring to _cppreference.com_. Still use
	// time-based fallback in such cases, as we won't do workarounds.
	//
	// "This function is not fully implemented in some standard libraries. For
	//  example, LLVM libc++ always returns zero even though the device is
	//  non-deterministic. In comparison, Microsoft Visual C++ implementation
	//  always returns 32, and boost.random returns 10.
	//  The entropy of the Linux kernel device /dev/urandom may be obtained
	//  using ioctl RNDGETENTCNT - that's what std::random_device::entropy() in
	//  GNU libstdc++ uses as of version 8.1"
	//  -- https://en.cppreference.com/w/cpp/numeric/random/random_device/entropy
	if (randomDevice.entropy() != 0.0)
		E::seed(randomDevice());
	else
		E::seed(std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count());
}

/**
 * Generate random integer using uniform distribution.
 * @tparam T integer type.
 * @tparam E random number generator engine.
 * @param from lower bound of a set of generated random numbers.
 * @param from upper bound of a set of generated random numbers.
 * @return randomly generated integer.
 */
template <typename T, typename E = SeededEngine<std::mt19937>>
typename std::enable_if<IsIntType<T>::value, T>::type rand(T from = std::numeric_limits<T>::lowest(), T to = std::numeric_limits<T>::max())
{
	static E engine;    // Use static variable to prevent frequent allocation/deallocation ("mt19937 use 5000 bytes of memory for each creation (which is bad for performance if we create it too frequently)" -- https://github.com/effolkronium/random).

	std::uniform_int_distribution<T> distribution(from, to);

	return distribution(engine);
}

/**
 * Generate random floating point number using uniform distribution. Fractions are generated within range [@p 0.0, @p 1.0) and then
 * multiplied by @p 2 raised to random exponent [@a fromExponent, @a toExponent]. Sign is randomly applied to the resulting value.
 * @tparam T floating point number type.
 * @tparam E random number generator engine.
 * @param fromExponent lower bound of a set of powers of base 2 exponents to be used to multiply a randomly generated fraction from
 * [@p 0.0, @p 1.0) range.
 * @param toExponent upper bound of a set of powers of base 2 exponents to be used to multiply a randomly generated fraction from
 * [@p 0.0, @p 1.0) range.
 * @return randomly generated floating point number.
 */
template <typename T, typename E = SeededEngine<std::mt19937>>
typename std::enable_if<std::is_floating_point<T>::value, T>::type rand(int fromExponent = std::numeric_limits<T>::min_exponent, int toExponent = std::numeric_limits<T>::max_exponent)
{
	static E engine;    // Use static variable to prevent frequent allocation/deallocation ("mt19937 use 5000 bytes of memory for each creation (which is bad for performance if we create it too frequently)" -- https://github.com/effolkronium/random).

	std::uniform_real_distribution<T> fracDistribution(0.0, 1.0);	// A fraction within range [0.0, 1.0).
	std::uniform_int_distribution<int> expDistribution(fromExponent, toExponent);

	return rand<bool>() ? ldexp(fracDistribution(engine), expDistribution(engine)) : -ldexp(fracDistribution(engine), expDistribution(engine));
}

/**
 * Generate random Boolean value using Bernoulli distribution.
 * @tparam T boolean type.
 * @tparam E random number generator engine.
 * @param p propbablity of generating @p true.
 * @return one of the Boolean values: @p true or @p false.
 */
template <typename T, typename E = SeededEngine<std::mt19937>>
typename std::enable_if<std::is_same<T, bool>::value, T>::type rand(double p = 0.5)
{
	static E engine;    // Use static variable to prevent frequent allocation/deallocation ("mt19937 use 5000 bytes of memory for each creation (which is bad for performance if we create it too frequently)" -- https://github.com/effolkronium/random).

	std::bernoulli_distribution distribution(p);

	return distribution(engine);
}

/**
 * Generate random character.
 * @tparam T QChar type.
 * @tparam E random number generator engine.
 * @param category character category.
 * @return random character.
 */
template <typename T, typename E = SeededEngine<std::mt19937>>
typename std::enable_if<std::is_same<T, QChar>::value, QChar>::type rand(QChar::Category category)
{
	static E engine;    // Use static variable to prevent frequent allocation/deallocation ("mt19937 use 5000 bytes of memory for each creation (which is bad for performance if we create it too frequently)" -- https://github.com/effolkronium/random).
	static QMultiHash<int, QChar> categorySets;		// Key denotes category of specific charecters.

	if (categorySets.empty()) {
		// Initialize categorized sets of characters.
		for (char16_t c = 0; c < std::numeric_limits<char16_t>::max(); c++)
			categorySets.insert(QChar::category(c), c);
		categorySets.insert(QChar::category(std::numeric_limits<char16_t>::max()), std::numeric_limits<char16_t>::max());
	}

	return categorySets.values(category).at(rand(0, categorySets.values(category).size() - 1));
}

/**
 * Generate random string.
 * @tparam T QString type.
 * @tparam E random number generator engine.
 * @param length string length.
 * @param categories character categories of which string should be composed from.
 * @return randomly generated string.
 */
template <typename T, typename E = SeededEngine<std::mt19937>>
typename std::enable_if<std::is_same<T, QString>::value, T>::type rand(int length = rand(0, 255), QList<QChar::Category> categories = {QChar::Letter_Uppercase, QChar::Letter_Lowercase, QChar::Number_DecimalDigit})
{
	static E engine;    // Use static variable to prevent frequent allocation/deallocation ("mt19937 use 5000 bytes of memory for each creation (which is bad for performance if we create it too frequently)" -- https://github.com/effolkronium/random).

	QString result("");
	for (int i = 0; i < length; i++)
		result.append(rand<QChar>(categories.at(rand(0, categories.size() - 1))));

	return result;
}

/**
 * Generate random string list.
 * @tparam T QStringList type.
 * @tparam E random number generator engine.
 * @param size string list size.
 * @param length strings length.
 * @param categories character categories of which strings should be composed from.
 * @return randomly generated string list.
 */
template <typename T, typename E = SeededEngine<std::mt19937>>
typename std::enable_if<std::is_same<T, QStringList>::value, T>::type rand(int size = rand(0, 255), int length = rand(0, 255), QList<QChar::Category> categories = {QChar::Letter_Uppercase, QChar::Letter_Lowercase, QChar::Number_DecimalDigit})
{
	static E engine;    // Use static variable to prevent frequent allocation/deallocation ("mt19937 use 5000 bytes of memory for each creation (which is bad for performance if we create it too frequently)" -- https://github.com/effolkronium/random).

	QStringList result;
	for (int i = 0; i < size; i++)
		result.append(rand<QString>(length, categories));

	return result;
}

/**
 * Randomize array.
 * @tparam T type of array elements.
 * @tparam E random number genererator engine.
 * @tparam ARGS arguments to be passed to underlying rand() function.
 * @param ptr array pointer.
 * @param size array size.
 * @param arguments to be passed to underlying rand() function for each array
 * element.
 */
template <typename T, typename E = SeededEngine<std::mt19937>, typename... ARGS>
void rand(T * ptr, std::size_t size, ARGS... args)
{
	while (size > 0) {
		*ptr = rand<T, E>(args...);
		ptr++;
		size--;
	}
}

}
}

#endif

//(c)MP: Copyright © 2019, Michal Policht <michpolicht@gmail.com>. All rights reserved.
//(c)MP: This file is a part of CuteHMI.
//(c)MP: CuteHMI is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
//(c)MP: CuteHMI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
//(c)MP: You should have received a copy of the GNU Lesser General Public License along with CuteHMI.  If not, see <https://www.gnu.org/licenses/>.
<commit_msg>Call standard 'ldexp' with namespace name.<commit_after>#ifndef H_EXTENSIONS_CUTEHMI_TEST_0_INCLUDE_CUTEHMI_TEST_RANDOM_HPP
#define H_EXTENSIONS_CUTEHMI_TEST_0_INCLUDE_CUTEHMI_TEST_RANDOM_HPP

#include "IsIntType.hpp"

#include <QChar>
#include <QString>
#include <QList>
#include <QMultiHash>

#include <random>
#include <chrono>
#include <limits>
#include <type_traits>

namespace cutehmi {
namespace test {

/**
 * Seeded engine. This class extends random generator class specified by @a E
 * template parameter and behaves exactly like extended class, except it seeds
 * itself within a constructor.
 * @tparam E random number generator engine.
 */
template <class E = std::mt19937>
class SeededEngine:
	public E
{
	public:
		/**
		 * Default constructor.
		 */
		SeededEngine();
};

template <class E>
SeededEngine<E>::SeededEngine()
{
	std::random_device randomDevice;

	// Some implementations do not have non-deterministic std::random_device.
	// Check out entropy of std::random_device. If it's zero, then fallback to
	// time-based seed.
	//
	// Note that sometimes it's std::random_device::entropy(), which is not
	// implemented properly, accodring to _cppreference.com_. Still use
	// time-based fallback in such cases, as we won't do workarounds.
	//
	// "This function is not fully implemented in some standard libraries. For
	//  example, LLVM libc++ always returns zero even though the device is
	//  non-deterministic. In comparison, Microsoft Visual C++ implementation
	//  always returns 32, and boost.random returns 10.
	//  The entropy of the Linux kernel device /dev/urandom may be obtained
	//  using ioctl RNDGETENTCNT - that's what std::random_device::entropy() in
	//  GNU libstdc++ uses as of version 8.1"
	//  -- https://en.cppreference.com/w/cpp/numeric/random/random_device/entropy
	if (randomDevice.entropy() != 0.0)
		E::seed(randomDevice());
	else
		E::seed(std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count());
}

/**
 * Generate random integer using uniform distribution.
 * @tparam T integer type.
 * @tparam E random number generator engine.
 * @param from lower bound of a set of generated random numbers.
 * @param from upper bound of a set of generated random numbers.
 * @return randomly generated integer.
 */
template <typename T, typename E = SeededEngine<std::mt19937>>
typename std::enable_if<IsIntType<T>::value, T>::type rand(T from = std::numeric_limits<T>::lowest(), T to = std::numeric_limits<T>::max())
{
	static E engine;    // Use static variable to prevent frequent allocation/deallocation ("mt19937 use 5000 bytes of memory for each creation (which is bad for performance if we create it too frequently)" -- https://github.com/effolkronium/random).

	std::uniform_int_distribution<T> distribution(from, to);

	return distribution(engine);
}

/**
 * Generate random floating point number using uniform distribution. Fractions are generated within range [@p 0.0, @p 1.0) and then
 * multiplied by @p 2 raised to random exponent [@a fromExponent, @a toExponent]. Sign is randomly applied to the resulting value.
 * @tparam T floating point number type.
 * @tparam E random number generator engine.
 * @param fromExponent lower bound of a set of powers of base 2 exponents to be used to multiply a randomly generated fraction from
 * [@p 0.0, @p 1.0) range.
 * @param toExponent upper bound of a set of powers of base 2 exponents to be used to multiply a randomly generated fraction from
 * [@p 0.0, @p 1.0) range.
 * @return randomly generated floating point number.
 */
template <typename T, typename E = SeededEngine<std::mt19937>>
typename std::enable_if<std::is_floating_point<T>::value, T>::type rand(int fromExponent = std::numeric_limits<T>::min_exponent, int toExponent = std::numeric_limits<T>::max_exponent)
{
	static E engine;    // Use static variable to prevent frequent allocation/deallocation ("mt19937 use 5000 bytes of memory for each creation (which is bad for performance if we create it too frequently)" -- https://github.com/effolkronium/random).

	std::uniform_real_distribution<T> fracDistribution(0.0, 1.0);	// A fraction within range [0.0, 1.0).
	std::uniform_int_distribution<int> expDistribution(fromExponent, toExponent);

	return rand<bool>() ? std::ldexp(fracDistribution(engine), expDistribution(engine)) : -std::ldexp(fracDistribution(engine), expDistribution(engine));
}

/**
 * Generate random Boolean value using Bernoulli distribution.
 * @tparam T boolean type.
 * @tparam E random number generator engine.
 * @param p propbablity of generating @p true.
 * @return one of the Boolean values: @p true or @p false.
 */
template <typename T, typename E = SeededEngine<std::mt19937>>
typename std::enable_if<std::is_same<T, bool>::value, T>::type rand(double p = 0.5)
{
	static E engine;    // Use static variable to prevent frequent allocation/deallocation ("mt19937 use 5000 bytes of memory for each creation (which is bad for performance if we create it too frequently)" -- https://github.com/effolkronium/random).

	std::bernoulli_distribution distribution(p);

	return distribution(engine);
}

/**
 * Generate random character.
 * @tparam T QChar type.
 * @tparam E random number generator engine.
 * @param category character category.
 * @return random character.
 */
template <typename T, typename E = SeededEngine<std::mt19937>>
typename std::enable_if<std::is_same<T, QChar>::value, QChar>::type rand(QChar::Category category)
{
	static E engine;    // Use static variable to prevent frequent allocation/deallocation ("mt19937 use 5000 bytes of memory for each creation (which is bad for performance if we create it too frequently)" -- https://github.com/effolkronium/random).
	static QMultiHash<int, QChar> categorySets;		// Key denotes category of specific charecters.

	if (categorySets.empty()) {
		// Initialize categorized sets of characters.
		for (char16_t c = 0; c < std::numeric_limits<char16_t>::max(); c++)
			categorySets.insert(QChar::category(c), c);
		categorySets.insert(QChar::category(std::numeric_limits<char16_t>::max()), std::numeric_limits<char16_t>::max());
	}

	return categorySets.values(category).at(rand(0, categorySets.values(category).size() - 1));
}

/**
 * Generate random string.
 * @tparam T QString type.
 * @tparam E random number generator engine.
 * @param length string length.
 * @param categories character categories of which string should be composed from.
 * @return randomly generated string.
 */
template <typename T, typename E = SeededEngine<std::mt19937>>
typename std::enable_if<std::is_same<T, QString>::value, T>::type rand(int length = rand(0, 255), QList<QChar::Category> categories = {QChar::Letter_Uppercase, QChar::Letter_Lowercase, QChar::Number_DecimalDigit})
{
	static E engine;    // Use static variable to prevent frequent allocation/deallocation ("mt19937 use 5000 bytes of memory for each creation (which is bad for performance if we create it too frequently)" -- https://github.com/effolkronium/random).

	QString result("");
	for (int i = 0; i < length; i++)
		result.append(rand<QChar>(categories.at(rand(0, categories.size() - 1))));

	return result;
}

/**
 * Generate random string list.
 * @tparam T QStringList type.
 * @tparam E random number generator engine.
 * @param size string list size.
 * @param length strings length.
 * @param categories character categories of which strings should be composed from.
 * @return randomly generated string list.
 */
template <typename T, typename E = SeededEngine<std::mt19937>>
typename std::enable_if<std::is_same<T, QStringList>::value, T>::type rand(int size = rand(0, 255), int length = rand(0, 255), QList<QChar::Category> categories = {QChar::Letter_Uppercase, QChar::Letter_Lowercase, QChar::Number_DecimalDigit})
{
	static E engine;    // Use static variable to prevent frequent allocation/deallocation ("mt19937 use 5000 bytes of memory for each creation (which is bad for performance if we create it too frequently)" -- https://github.com/effolkronium/random).

	QStringList result;
	for (int i = 0; i < size; i++)
		result.append(rand<QString>(length, categories));

	return result;
}

/**
 * Randomize array.
 * @tparam T type of array elements.
 * @tparam E random number genererator engine.
 * @tparam ARGS arguments to be passed to underlying rand() function.
 * @param ptr array pointer.
 * @param size array size.
 * @param arguments to be passed to underlying rand() function for each array
 * element.
 */
template <typename T, typename E = SeededEngine<std::mt19937>, typename... ARGS>
void rand(T * ptr, std::size_t size, ARGS... args)
{
	while (size > 0) {
		*ptr = rand<T, E>(args...);
		ptr++;
		size--;
	}
}

}
}

#endif

//(c)MP: Copyright © 2019, Michal Policht <michpolicht@gmail.com>. All rights reserved.
//(c)MP: This file is a part of CuteHMI.
//(c)MP: CuteHMI is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
//(c)MP: CuteHMI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
//(c)MP: You should have received a copy of the GNU Lesser General Public License along with CuteHMI.  If not, see <https://www.gnu.org/licenses/>.
<|endoftext|>


<commit_before>#include "gtest/gtest.h"
#include "ROOT/THist.hxx"
#include "ROOT/THistBinIter.hxx"
#include <cmath>
#include <limits>

using namespace ROOT::Experimental;

// Test FindBin() in all its glory.

// Basic binning on a Equidistant axis.
TEST(AxisBinning, EquiDistBasic) {
   TAxisEquidistant ax("TITLE", 10, -1., 1.);
   EXPECT_EQ(1, ax.FindBin(-.999));
   EXPECT_EQ(5, ax.FindBin(-.001));
   EXPECT_EQ(10, ax.FindBin(0.999));
   EXPECT_EQ(0, ax.FindBin(-2.));
   EXPECT_EQ(11, ax.FindBin(2000.));

   EXPECT_GE(6, ax.FindBin(std::numeric_limits<double>::min()));
   EXPECT_LE(5, ax.FindBin(std::numeric_limits<double>::min()));
   EXPECT_GE(6, ax.FindBin(-std::numeric_limits<double>::min()));
   EXPECT_LE(5, ax.FindBin(-std::numeric_limits<double>::min()));

   EXPECT_EQ(11, ax.FindBin(std::numeric_limits<double>::max()));
   EXPECT_EQ(0, ax.FindBin(-std::numeric_limits<double>::max()));
}

// Epsilon bin widths.
TEST(AxisBinning, EquiDistEps) {
   static constexpr auto eps = std::numeric_limits<double>::epsilon();
   TAxisEquidistant ax("TITLE", 10, 0., eps * 10.);
   EXPECT_LE(0, ax.FindBin(0.5*eps));
   EXPECT_GE(1, ax.FindBin(0.5*eps));

   EXPECT_LE(5, ax.FindBin(5.*eps));
   EXPECT_GE(6, ax.FindBin(5.*eps));

   EXPECT_LE(10, ax.FindBin(10.*eps));
   EXPECT_GE(11, ax.FindBin(10.*eps));

   EXPECT_EQ(0, ax.FindBin(-2000.*eps));
   EXPECT_EQ(11, ax.FindBin(2000.*eps));
   EXPECT_EQ(1, ax.FindBin(std::numeric_limits<double>::min()));
   EXPECT_EQ(0, ax.FindBin(-std::numeric_limits<double>::min()));
   EXPECT_EQ(11, ax.FindBin(std::numeric_limits<double>::max()));
   EXPECT_EQ(0, ax.FindBin(-std::numeric_limits<double>::max()));
}
<commit_msg>Test FindBin() for irregular binning, histograms.<commit_after>#include "gtest/gtest.h"
#include "ROOT/THist.hxx"
#include "ROOT/THistBinIter.hxx"
#include <cmath>
#include <limits>

using namespace ROOT::Experimental;

// Test FindBin() in all its glory.

// Basic binning on a Equidistant axis.
TEST(AxisBinning, EquidistBasic) {
   TAxisEquidistant ax("TITLE", 10, -1., 1.);
   EXPECT_EQ(1, ax.FindBin(-.999));
   EXPECT_EQ(5, ax.FindBin(-.001));
   EXPECT_EQ(10, ax.FindBin(0.999));
   EXPECT_EQ(0, ax.FindBin(-2.));
   EXPECT_EQ(11, ax.FindBin(2000.));

   EXPECT_GE(6, ax.FindBin(std::numeric_limits<double>::min()));
   EXPECT_LE(5, ax.FindBin(std::numeric_limits<double>::min()));
   EXPECT_GE(6, ax.FindBin(-std::numeric_limits<double>::min()));
   EXPECT_LE(5, ax.FindBin(-std::numeric_limits<double>::min()));

   EXPECT_EQ(11, ax.FindBin(std::numeric_limits<double>::max()));
   EXPECT_EQ(0, ax.FindBin(-std::numeric_limits<double>::max()));
}

// Epsilon bin widths.
TEST(AxisBinning, EquidistEpsBins) {
   static constexpr auto eps = std::numeric_limits<double>::min();
   TAxisEquidistant ax("TITLE", 10, 0., eps * 10.);
   EXPECT_LE(0, ax.FindBin(0.5*eps));
   EXPECT_GE(1, ax.FindBin(0.5*eps));

   EXPECT_LE(5, ax.FindBin(5.*eps));
   EXPECT_GE(6, ax.FindBin(5.*eps));

   EXPECT_LE(10, ax.FindBin(10.*eps));
   EXPECT_GE(11, ax.FindBin(10.*eps));

   EXPECT_EQ(0, ax.FindBin(-2000.*eps));
   EXPECT_EQ(11, ax.FindBin(2000.*eps));
   EXPECT_LE(1, ax.FindBin(std::numeric_limits<double>::min()));
   EXPECT_GE(2, ax.FindBin(std::numeric_limits<double>::min()));
   EXPECT_LE(0, ax.FindBin(-std::numeric_limits<double>::min()));
   EXPECT_GE(1, ax.FindBin(-std::numeric_limits<double>::min()));
   EXPECT_EQ(11, ax.FindBin(std::numeric_limits<double>::max()));
   EXPECT_EQ(0, ax.FindBin(-std::numeric_limits<double>::max()));
}

// Basic binning on an Irregular axis.
TEST(AxisBinning, IrregularBasic) {
   TAxisIrregular ax("TITLE", {-5., 0., 0.1, 1., 10., 100.});
   EXPECT_EQ(2, ax.FindBin(.001));
   EXPECT_EQ(1, ax.FindBin(-.001));
   EXPECT_EQ(5, ax.FindBin(99.));
   EXPECT_EQ(0, ax.FindBin(-6.));
   EXPECT_EQ(6, ax.FindBin(2000.));

   EXPECT_GE(2, ax.FindBin(std::numeric_limits<double>::min()));
   EXPECT_LE(1, ax.FindBin(std::numeric_limits<double>::min()));
   EXPECT_GE(2, ax.FindBin(-std::numeric_limits<double>::min()));
   EXPECT_LE(1, ax.FindBin(-std::numeric_limits<double>::min()));

   EXPECT_EQ(6, ax.FindBin(std::numeric_limits<double>::max()));
   EXPECT_EQ(0, ax.FindBin(-std::numeric_limits<double>::max()));
}

// Limit bin widths on an Irregular axis.
TEST(AxisBinning, IrregularEpsBins) {
   static constexpr auto eps = std::numeric_limits<double>::min();
   TAxisIrregular ax("TITLE", {0., eps, 2.*eps, 3.*eps, 4.*eps, 5.*eps});
   EXPECT_LE(0, ax.FindBin(0.5*eps));
   EXPECT_GE(1, ax.FindBin(0.5*eps));

   EXPECT_LE(3, ax.FindBin(3.*eps));
   EXPECT_GE(4, ax.FindBin(3.*eps));

   EXPECT_LE(5, ax.FindBin(5.*eps));
   EXPECT_GE(6, ax.FindBin(5.*eps));

   EXPECT_EQ(0, ax.FindBin(-2000.*eps));
   EXPECT_EQ(6, ax.FindBin(2000.*eps));
   EXPECT_EQ(1, ax.FindBin(std::numeric_limits<double>::min()));
   EXPECT_EQ(0, ax.FindBin(-std::numeric_limits<double>::min()));
   EXPECT_EQ(6, ax.FindBin(std::numeric_limits<double>::max()));
   EXPECT_EQ(0, ax.FindBin(-std::numeric_limits<double>::max()));
}

// Histogram binning on a Equidistant axis.
TEST(HistImplBinning, Equidist1D) {
   Detail::THistImpl<Detail::THistData<1, double, Detail::THistDataDefaultStorage, THistStatContent>,
                     TAxisEquidistant> hist(TAxisEquidistant(10, 0., 1.));

   EXPECT_EQ(5, hist.GetBinIndex({.45}));
   EXPECT_EQ(10, hist.GetBinIndex({.999}));
   EXPECT_EQ(1, hist.GetBinIndex({.001}));
   EXPECT_EQ(0, hist.GetBinIndex({-.001}));
   EXPECT_EQ(11, hist.GetBinIndex({1.001}));

   EXPECT_GE(1, hist.GetBinIndex({std::numeric_limits<double>::min()}));
   EXPECT_LE(0, hist.GetBinIndex({std::numeric_limits<double>::min()}));
   EXPECT_GE(1, hist.GetBinIndex({-std::numeric_limits<double>::min()}));
   EXPECT_LE(0, hist.GetBinIndex({-std::numeric_limits<double>::min()}));

   EXPECT_EQ(11, hist.GetBinIndex({std::numeric_limits<double>::max()}));
   EXPECT_EQ(0, hist.GetBinIndex({-std::numeric_limits<double>::max()}));
}

TEST(HistImplBinning, EquiDist2D) {
   Detail::THistImpl<Detail::THistData<2, double, Detail::THistDataDefaultStorage, THistStatContent>,
                     TAxisEquidistant, TAxisEquidistant>
      hist(TAxisEquidistant(2, 0., 2.), TAxisEquidistant(2, -1., 1.));

   EXPECT_EQ( 0, hist.GetBinIndex({-100., -100.}));
   EXPECT_EQ( 1, hist.GetBinIndex({0.5, -100.}));
   EXPECT_EQ( 2, hist.GetBinIndex({1.5, -100.}));
   EXPECT_EQ( 3, hist.GetBinIndex({100., -100.}));
   EXPECT_EQ( 4, hist.GetBinIndex({-100., -0.5}));
   EXPECT_EQ( 5, hist.GetBinIndex({0.5, -0.5}));
   EXPECT_EQ( 6, hist.GetBinIndex({1.5, -0.5}));
   EXPECT_EQ( 7, hist.GetBinIndex({100., -0.5}));
   EXPECT_EQ( 8, hist.GetBinIndex({-100., 0.5}));
   EXPECT_EQ( 9, hist.GetBinIndex({0.5, 0.5}));
   EXPECT_EQ(10, hist.GetBinIndex({1.5, 0.5}));
   EXPECT_EQ(11, hist.GetBinIndex({100., 0.5}));
   EXPECT_EQ(12, hist.GetBinIndex({-100., 100.}));
   EXPECT_EQ(13, hist.GetBinIndex({0.5, 100.}));
   EXPECT_EQ(14, hist.GetBinIndex({1.5, 100.}));
   EXPECT_EQ(15, hist.GetBinIndex({100., 100.}));

   EXPECT_EQ( 0, hist.GetBinIndex({-std::numeric_limits<double>::max(), -std::numeric_limits<double>::max()}));
   EXPECT_EQ( 3, hist.GetBinIndex({ std::numeric_limits<double>::max(), -std::numeric_limits<double>::max()}));
   EXPECT_EQ(12, hist.GetBinIndex({-std::numeric_limits<double>::max(),  std::numeric_limits<double>::max()}));
   EXPECT_EQ(15, hist.GetBinIndex({ std::numeric_limits<double>::max(),  std::numeric_limits<double>::max()}));
}
<|endoftext|>


<commit_before>#include "NeuralNetwork.h"

NeuralNetwork::NeuralNetwork()
{
    generation = 0;
    dna = new Genome();
}

NeuralNetwork::NeuralNetwork(std::string dir)
{
    dna = new Genome();
    generation = 0;

    dna -> loadFromFile(dir);
    updateStructure();

}

NeuralNetwork::NeuralNetwork(Genome code)
{
    dna = new Genome();
    generation = 0;
    dna -> copyIntoGenome(code);
    updateStructure();
}

NeuralNetwork::~NeuralNetwork()
{
    delete dna;

    for(auto & node : inputs)
        delete node;

    for(auto & vec : hiddenLayer)
        for(auto & node : vec)
            delete node;

    for(auto & node : outputs)
        delete node;
}

void NeuralNetwork::updateStructure()
{
    //Create the nodes in the network.
    //Create the input layer.
    for(unsigned int i = 0; i < dna -> getInput(); ++i)
        inputs.push_back(new Node());

    //Create the hidden layer.
    std::vector<unsigned int> topo = dna -> getHidden();
    unsigned int size = topo.size();

    hiddenLayer.resize(size);
    for(unsigned int i = 0; i < size; ++i)
        for(unsigned int j = 0; j < topo[i]; ++j)
            hiddenLayer[i].push_back(new Node());

    //Create the output layer.
    for(unsigned int i = 0; i < dna -> getOutput(); ++i)
        outputs.push_back(new Node());

    //Connect structure based on the genes in the genome and add the correct weights.
    unsigned int numConnections = dna -> getGenes().size();
    Gene currentGene;
    Node * first;
    Node * last;
    Weight * weight;
    for(unsigned int i = 0; i < numConnections; ++i)
    {
        currentGene = dna -> getGene(i);
        first = findNodeWithID(currentGene.inID);
        last = findNodeWithID(currentGene.outID);
        first -> addForward(last,first);
        weight = first -> getLastForward();
        weight -> weight() = currentGene.weight;
        last -> addBackwards(weight);

    }

}

void NeuralNetwork::mutate()
{

}

void NeuralNetwork::saveNetwork(std::string name)
{
    name += ".charzar"; //maybe dont do it this way
    dna -> saveGenome(name);
}

void NeuralNetwork::loadFromFile(std::string dir)
{
    dna -> loadFromFile(dir);
    updateStructure();
}

//There is a better way to write this code;
Node * NeuralNetwork::findNodeWithID(unsigned int ID)
{
    //calculates the size of the hiddenLayer.
    unsigned int hiddenLayerSize = 0;
    for(auto & vec : hiddenLayer)
        hiddenLayerSize += vec.size();

    if(ID < inputs.size())
    {
        return inputs[ID];
    }
    else if (ID < inputs.size() + hiddenLayerSize)
    {
        ID -= inputs.size();
        unsigned int count = 0;

        for(auto & vec : hiddenLayer)
        {
            for(auto & node : vec)
            {
                if(count == ID)
                    return node;
                ++count;
            }
        }
    }
    else
    {
        ID -= inputs.size() + hiddenLayerSize;
        return outputs[ID];
    }
    return NULL; //If this works this will never execute.
}
<commit_msg>add new structure<commit_after>#include "NeuralNetwork.h"

NeuralNetwork::NeuralNetwork()
{
    generation = 0;
    dna = new Genome();
}

NeuralNetwork::NeuralNetwork(std::string dir)
{
    dna = new Genome();
    generation = 0;

    dna -> loadFromFile(dir);
    updateStructure();

}

NeuralNetwork::NeuralNetwork(Genome code)
{
    dna = new Genome();
    generation = 0;
    dna -> copyIntoGenome(code);
    updateStructure();
}

NeuralNetwork::~NeuralNetwork()
{
    delete dna;

    for(auto & node : inputs)
        delete node;

    for(auto & vec : hiddenLayer)
        for(auto & node : vec)
            delete node;

    for(auto & node : outputs)
        delete node;
}

void NeuralNetwork::updateStructure()
{
    //Create the nodes in the network.
    //Create the input layer.
    for(unsigned int i = 0; i < dna -> getInput(); ++i)
        inputs.push_back(new Node());

    //Create the hidden layer.
    std::vector<unsigned int> topo = dna -> getHidden();
    unsigned int size = topo.size();

    hiddenLayer.resize(size);
    for(unsigned int i = 0; i < size; ++i)
        for(unsigned int j = 0; j < topo[i]; ++j)
            hiddenLayer[i].push_back(new Node());

    //Create the output layer.
    for(unsigned int i = 0; i < dna -> getOutput(); ++i)
        outputs.push_back(new Node());

    //Connect structure based on the genes in the genome and add the correct weights.
    unsigned int numConnections = dna -> getGenes().size();
    Gene currentGene;
    Node * first;
    Node * last;
    Weight * weight;
    for(unsigned int i = 0; i < numConnections; ++i)
    {
        currentGene = dna -> getGene(i);
        first = findNodeWithID(currentGene.inID);
        last = findNodeWithID(currentGene.outID);
        first -> addForward(last);
        last -> addBackward(first);
        last -> weight() = currentGene.weight;
    }

}

void NeuralNetwork::mutate()
{

}

void NeuralNetwork::saveNetwork(std::string name)
{
    name += ".charzar"; //maybe dont do it this way
    dna -> saveGenome(name);
}

void NeuralNetwork::loadFromFile(std::string dir)
{
    dna -> loadFromFile(dir);
    updateStructure();
}

//There is a better way to write this code;
Node * NeuralNetwork::findNodeWithID(unsigned int ID)
{
    //calculates the size of the hiddenLayer.
    unsigned int hiddenLayerSize = 0;
    for(auto & vec : hiddenLayer)
        hiddenLayerSize += vec.size();

    if(ID < inputs.size())
    {
        return inputs[ID];
    }
    else if (ID < inputs.size() + hiddenLayerSize)
    {
        ID -= inputs.size();
        unsigned int count = 0;

        for(auto & vec : hiddenLayer)
        {
            for(auto & node : vec)
            {
                if(count == ID)
                    return node;
                ++count;
            }
        }
    }
    else
    {
        ID -= inputs.size() + hiddenLayerSize;
        return outputs[ID];
    }
    return NULL; //If this works this will never execute.
}
<|endoftext|>


<commit_before>#ifdef _WIN32
#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
#endif

#include <iostream>
#include <fstream>
#include <cctype>
#include <sys/stat.h>
#include "file.hpp"
#include "context.hpp"

namespace Sass {
  namespace File {
    using namespace std;

    string base_name(string path)
    {
      size_t pos = path.find_last_of('/');
      if (pos == string::npos) return path;
      else                     return path.substr(pos+1);
    }

    string dir_name(string path)
    {
      size_t pos = path.find_last_of('/');
      if (pos == string::npos) return "";
      else                     return path.substr(0, pos+1);
    }

    string join_paths(string l, string r)
    {
      if (l.empty()) return r;
      if (r.empty()) return l;
      if (is_absolute_path(r)) return r;

      if (l[l.length()-1] != '/') l += '/';

      while ((r.length() > 3) && (r.substr(0, 3) == "../")) {
        r = r.substr(3);
        size_t index = l.find_last_of('/', l.length() - 2);
        l = l.substr(0, index + 1);
      }

      return l + r;
    }

    bool is_absolute_path(const string& path)
    {
      if (path[0] == '/') return true;
      // TODO: UN-HACKIFY THIS
      #ifdef _WIN32
      if (path.length() >= 2 && isalpha(path[0]) && path[1] == ':') return true;
      #endif
      return false;
    }

    string make_absolute_path(const string& path, const string& cwd)
    {
      return (is_absolute_path(path) ? path : join_paths(cwd, path));
    }

    string resolve_relative_path(const string& uri, const string& base, const string& cwd)
    {
      string absolute_uri = make_absolute_path(uri, cwd);
      string absolute_base = make_absolute_path(base, cwd);

      string stripped_uri = "";
      string stripped_base = "";

      size_t index = 0;
      size_t minSize = min(absolute_uri.size(), absolute_base.size());
      for (size_t i = 0; i < minSize; ++i) {
        if (absolute_uri[i] != absolute_base[i]) break;
        if (absolute_uri[i] == '/') index = i + 1;
      }
      for (size_t i = index; i < absolute_uri.size(); ++i) {
        stripped_uri += absolute_uri[i];
      }
      for (size_t i = index; i < absolute_base.size(); ++i) {
        stripped_base += absolute_base[i];
      }
      size_t directories = 0;
      for (size_t i = 0; i < stripped_base.size(); ++i) {
        if (stripped_base[i] == '/') ++directories;
      }
      string result = "";
      for (size_t i = 0; i < directories; ++i) {
        result += "../";
      }
      result += stripped_uri;

      return result;
    }

    char* resolve_and_load(string path, string& real_path)
    {
      // Resolution order for ambiguous imports:
      // (1) filename as given
      // (2) underscore + given
      // (3) underscore + given + extension
      // (4) given + extension
      char* contents = 0;
      // if the file isn't found with the given filename ...
      real_path = path;
      if (!(contents = read_file(real_path))) {
        string dir(dir_name(path));
        string base(base_name(path));
        string _base("_" + base);
        real_path = dir + _base;
        // if the file isn't found with '_' + filename ...
        if (!(contents = read_file(real_path))) {
          string _base_scss(_base + ".scss");
          real_path = dir + _base_scss;
          // if the file isn't found with '_' + filename + ".scss" ...
          if (!(contents = read_file(real_path))) {
            string base_scss(base + ".scss");
            // try filename + ".scss" as the last resort
            real_path = dir + base_scss;
            contents = read_file(real_path);
          }
        }
      }
      return contents;
    }

    char* read_file(string path)
    {
      struct stat st;
      if (stat(path.c_str(), &st) == -1 || S_ISDIR(st.st_mode)) return 0;
      ifstream file(path.c_str(), ios::in | ios::binary | ios::ate);
      char* contents = 0;
      if (file.is_open()) {
        size_t size = file.tellg();
        contents = new char[size + 1]; // extra byte for the null char
        file.seekg(0, ios::beg);
        file.read(contents, size);
        contents[size] = '\0';
        file.close();
      }
      return contents;
    }

  }
}
<commit_msg>handling the backslash folder-separator in case we're on Windows<commit_after>#ifdef _WIN32
#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
#endif

#include <iostream>
#include <fstream>
#include <cctype>
#include <sys/stat.h>
#include "file.hpp"
#include "context.hpp"

namespace Sass {
  namespace File {
    using namespace std;

    string base_name(string path)
    {
      size_t pos = path.find_last_of('/');
      #ifdef _WIN32
      if (pos == string::npos) pos = path.find_last_of('\\');
      #endif
      if (pos == string::npos) return path;
      else                     return path.substr(pos+1);
    }

    string dir_name(string path)
    {
      size_t pos = path.find_last_of('/');
      #ifdef _WIN32
      if (pos == string::npos) pos = path.find_last_of('\\');
      #endif
      if (pos == string::npos) return "";
      else                     return path.substr(0, pos+1);
    }

    string join_paths(string l, string r)
    {
      if (l.empty()) return r;
      if (r.empty()) return l;
      if (is_absolute_path(r)) return r;

      if (l[l.length()-1] != '/') l += '/';

      while ((r.length() > 3) && ((r.substr(0, 3) == "../") || (r.substr(0, 3)) == "..\\")) {
        r = r.substr(3);
        size_t pos = l.find_last_of('/', l.length() - 2);
        #ifdef _WIN32
        if (pos == string::npos) pos = path.find_last_of('\\', l.length() - 2);
        #endif
        l = l.substr(0, pos + 1);
      }

      return l + r;
    }

    bool is_absolute_path(const string& path)
    {
      if (path[0] == '/') return true;
      // TODO: UN-HACKIFY THIS
      #ifdef _WIN32
      if (path.length() >= 2 && isalpha(path[0]) && path[1] == ':') return true;
      #endif
      return false;
    }

    string make_absolute_path(const string& path, const string& cwd)
    {
      return (is_absolute_path(path) ? path : join_paths(cwd, path));
    }

    string resolve_relative_path(const string& uri, const string& base, const string& cwd)
    {
      string absolute_uri = make_absolute_path(uri, cwd);
      string absolute_base = make_absolute_path(base, cwd);

      string stripped_uri = "";
      string stripped_base = "";

      size_t index = 0;
      size_t minSize = min(absolute_uri.size(), absolute_base.size());
      for (size_t i = 0; i < minSize; ++i) {
        if (absolute_uri[i] != absolute_base[i]) break;
        if (absolute_uri[i] == '/') index = i + 1;
      }
      for (size_t i = index; i < absolute_uri.size(); ++i) {
        stripped_uri += absolute_uri[i];
      }
      for (size_t i = index; i < absolute_base.size(); ++i) {
        stripped_base += absolute_base[i];
      }
      size_t directories = 0;
      for (size_t i = 0; i < stripped_base.size(); ++i) {
        if (stripped_base[i] == '/') ++directories;
      }
      string result = "";
      for (size_t i = 0; i < directories; ++i) {
        result += "../";
      }
      result += stripped_uri;

      return result;
    }

    char* resolve_and_load(string path, string& real_path)
    {
      // Resolution order for ambiguous imports:
      // (1) filename as given
      // (2) underscore + given
      // (3) underscore + given + extension
      // (4) given + extension
      char* contents = 0;
      real_path = path;
      // if the file isn't found with the given filename ...
      if (!(contents = read_file(real_path))) {
        string dir(dir_name(path));
        string base(base_name(path));
        string _base("_" + base);
        real_path = dir + _base;
        // if the file isn't found with '_' + filename ...
        if (!(contents = read_file(real_path))) {
          string _base_scss(_base + ".scss");
          real_path = dir + _base_scss;
          // if the file isn't found with '_' + filename + ".scss" ...
          if (!(contents = read_file(real_path))) {
            string base_scss(base + ".scss");
            // try filename + ".scss" as the last resort
            real_path = dir + base_scss;
            contents = read_file(real_path);
          }
        }
      }
      return contents;
    }

    char* read_file(string path)
    {
      struct stat st;
      if (stat(path.c_str(), &st) == -1 || S_ISDIR(st.st_mode)) return 0;
      ifstream file(path.c_str(), ios::in | ios::binary | ios::ate);
      char* contents = 0;
      if (file.is_open()) {
        size_t size = file.tellg();
        contents = new char[size + 1]; // extra byte for the null char
        file.seekg(0, ios::beg);
        file.read(contents, size);
        contents[size] = '\0';
        file.close();
      }
      return contents;
    }

  }
}
<|endoftext|>


<commit_before>#define _IRR_STATIC_LIB_
#include <irrlicht.h>

#include "../3rdparty/portable-file-dialogs/portable-file-dialogs.h"
#include "../../ext/MitsubaLoader/CMitsubaLoader.h"

using namespace irr;
using namespace core;

bool quit = false;
class MyEventReceiver : public IEventReceiver
{
public:

	MyEventReceiver()
	{
	}

	bool OnEvent(const SEvent& event)
	{
		if (event.EventType == irr::EET_KEY_INPUT_EVENT && !event.KeyInput.PressedDown)
		{
			switch (event.KeyInput.Key)
			{
			case irr::KEY_ESCAPE:
			case irr::KEY_KEY_Q:
				quit = true;
				return true;
			default:
				break;
			}
		}

		return false;
	}

private:
};

class SimpleCallBack : public video::IShaderConstantSetCallBack
{
	int32_t mvpUniformLocation;
	int32_t cameraDirUniformLocation;
	int32_t texUniformLocation[4];
	video::E_SHADER_CONSTANT_TYPE mvpUniformType;
	video::E_SHADER_CONSTANT_TYPE cameraDirUniformType;
	video::E_SHADER_CONSTANT_TYPE texUniformType[4];
public:
	SimpleCallBack() : cameraDirUniformLocation(-1), cameraDirUniformType(video::ESCT_FLOAT_VEC3) {}

	virtual void PostLink(video::IMaterialRendererServices* services, const video::E_MATERIAL_TYPE& materialType, const core::vector<video::SConstantLocationNamePair>& constants)
	{
		for (size_t i = 0; i < constants.size(); i++)
		{
			if (constants[i].name == "MVP")
			{
				mvpUniformLocation = constants[i].location;
				mvpUniformType = constants[i].type;
			}
			else if (constants[i].name == "cameraPos")
			{
				cameraDirUniformLocation = constants[i].location;
				cameraDirUniformType = constants[i].type;
			}
		}
	}

	virtual void OnSetConstants(video::IMaterialRendererServices* services, int32_t userData)
	{
		core::vectorSIMDf modelSpaceCamPos;
		modelSpaceCamPos.set(services->getVideoDriver()->getTransform(video::E4X3TS_WORLD_VIEW_INVERSE).getTranslation());
		services->setShaderConstant(&modelSpaceCamPos, cameraDirUniformLocation, cameraDirUniformType, 1);
		services->setShaderConstant(services->getVideoDriver()->getTransform(video::EPTS_PROJ_VIEW_WORLD).pointer(), mvpUniformLocation, mvpUniformType, 1);
	}

	virtual void OnUnsetMaterial() {}
};

int main()
{
	srand(time(0));
	// create device with full flexibility over creation parameters
	// you can add more parameters if desired, check irr::SIrrlichtCreationParameters
	irr::SIrrlichtCreationParameters params;
	params.Bits = 24; //may have to set to 32bit for some platforms
	params.ZBufferBits = 24; //we'd like 32bit here
	params.DriverType = video::EDT_OPENGL; //! Only Well functioning driver, software renderer left for sake of 2D image drawing
	params.WindowSize = dimension2d<uint32_t>(800, 600);
	params.Fullscreen = false;
	params.Vsync = true; //! If supported by target platform
	params.Doublebuffer = true;
	params.Stencilbuffer = false; //! This will not even be a choice soon
	IrrlichtDevice* device = createDeviceEx(params);

	video::IVideoDriver* driver = device->getVideoDriver();

	scene::ISceneManager* smgr = device->getSceneManager();
	driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, true);
	scene::ICameraSceneNode* camera =
		smgr->addCameraSceneNodeFPS(0, 100.0f, 0.01f);
	camera->setPosition(core::vector3df(0, 0, 3));
	camera->setTarget(core::vector3df(0, 0, 0));
	camera->setNearValue(0.01f);
	camera->setFarValue(10000.0f);
	smgr->setActiveCamera(camera);
	device->getCursorControl()->setVisible(false);
	MyEventReceiver receiver;
	device->setEventReceiver(&receiver);

	SimpleCallBack* cb = new SimpleCallBack();
	video::E_MATERIAL_TYPE newMaterialType = (video::E_MATERIAL_TYPE)driver->getGPUProgrammingServices()->addHighLevelShaderMaterialFromFiles("../mesh.vert",
		"", "", "", //! No Geometry or Tessellation Shaders
		"../mesh.frag",
		3, video::EMT_SOLID, //! 3 vertices per primitive (this is tessellation shader relevant only
		cb, //! Our Shader Callback
		0); //! No custom user data
	cb->drop();

	if (device == 0)
		return 1; // could not create selected driver.

	io::IFileSystem* fs = device->getFileSystem();
	asset::IAssetManager* am = device->getAssetManager();

	am.addAssetLoader(core::make_smart_refctd_ptr<irr::ext::MitsubaLoader::CMitsubaLoader>(device));

#define MITSUBA_LOADER_TESTS

#ifdef MITSUBA_LOADER_TESTS
	std::string filePath = "../../media/mitsuba/staircase2/scene.xml";
#else
	pfd::message("Choose file to load", "Choose mitsuba XML file to load or ZIP containing an XML. \nIf you cancel or choosen file fails to load bathroom will be loaded.", pfd::choice::ok);
	pfd::open_file file("Choose XML file", "", { "XML files (.xml)", "*.xml" });
	std::string filePath = file.result().empty() ? "C:\\IrrlichtBAW\\/IrrlichtBAW\\examples_tests\\media\\mitsuba\\bathroom\\sce===
		netest.xml" : file.result()[0];
#endif
	asset::SAssetBundle meshes = am->getAsset(filePath, {});

	for (int i = 0; i < meshes.getSize(); i++)
	{
		asset::ICPUMesh* cpumesh = static_cast<asset::ICPUMesh*>((meshes.getContents().first + i)->get());
		video::IGPUMesh* gpumesh = driver->getGPUObjectsFromAssets(&cpumesh, (&cpumesh) + 1)[0];
		smgr->addMeshSceneNode(gpumesh)->setMaterialType(newMaterialType);
		gpumesh->drop();
	}

	while (!quit && device->run())
	{
		driver->beginScene(true, true, video::SColor(255, 0, 0, 255));

		//! This animates (moves) the camera and sets the transforms
		//! Also draws the meshbuffer
		smgr->drawAll();

		driver->endScene();
	}

	device->drop();
	return 0;
}
<commit_msg>small stuff (change PCs)<commit_after>#define _IRR_STATIC_LIB_
#include <irrlicht.h>

#include "../3rdparty/portable-file-dialogs/portable-file-dialogs.h"
#include "../../ext/MitsubaLoader/CMitsubaLoader.h"

using namespace irr;
using namespace core;

bool quit = false;
class MyEventReceiver : public IEventReceiver
{
public:

	MyEventReceiver()
	{
	}

	bool OnEvent(const SEvent& event)
	{
		if (event.EventType == irr::EET_KEY_INPUT_EVENT && !event.KeyInput.PressedDown)
		{
			switch (event.KeyInput.Key)
			{
			case irr::KEY_ESCAPE:
			case irr::KEY_KEY_Q:
				quit = true;
				return true;
			default:
				break;
			}
		}

		return false;
	}

private:
};

class SimpleCallBack : public video::IShaderConstantSetCallBack
{
	int32_t mvpUniformLocation;
	int32_t cameraDirUniformLocation;
	int32_t texUniformLocation[4];
	video::E_SHADER_CONSTANT_TYPE mvpUniformType;
	video::E_SHADER_CONSTANT_TYPE cameraDirUniformType;
	video::E_SHADER_CONSTANT_TYPE texUniformType[4];
public:
	SimpleCallBack() : cameraDirUniformLocation(-1), cameraDirUniformType(video::ESCT_FLOAT_VEC3) {}

	virtual void PostLink(video::IMaterialRendererServices* services, const video::E_MATERIAL_TYPE& materialType, const core::vector<video::SConstantLocationNamePair>& constants)
	{
		for (size_t i = 0; i < constants.size(); i++)
		{
			if (constants[i].name == "MVP")
			{
				mvpUniformLocation = constants[i].location;
				mvpUniformType = constants[i].type;
			}
			else if (constants[i].name == "cameraPos")
			{
				cameraDirUniformLocation = constants[i].location;
				cameraDirUniformType = constants[i].type;
			}
		}
	}

	virtual void OnSetConstants(video::IMaterialRendererServices* services, int32_t userData)
	{
		core::vectorSIMDf modelSpaceCamPos;
		modelSpaceCamPos.set(services->getVideoDriver()->getTransform(video::E4X3TS_WORLD_VIEW_INVERSE).getTranslation());
		services->setShaderConstant(&modelSpaceCamPos, cameraDirUniformLocation, cameraDirUniformType, 1);
		services->setShaderConstant(services->getVideoDriver()->getTransform(video::EPTS_PROJ_VIEW_WORLD).pointer(), mvpUniformLocation, mvpUniformType, 1);
	}

	virtual void OnUnsetMaterial() {}
};

int main()
{
	srand(time(0));
	// create device with full flexibility over creation parameters
	// you can add more parameters if desired, check irr::SIrrlichtCreationParameters
	irr::SIrrlichtCreationParameters params;
	params.Bits = 24; //may have to set to 32bit for some platforms
	params.ZBufferBits = 24; //we'd like 32bit here
	params.DriverType = video::EDT_OPENGL; //! Only Well functioning driver, software renderer left for sake of 2D image drawing
	params.WindowSize = dimension2d<uint32_t>(800, 600);
	params.Fullscreen = false;
	params.Vsync = true; //! If supported by target platform
	params.Doublebuffer = true;
	params.Stencilbuffer = false; //! This will not even be a choice soon
	IrrlichtDevice* device = createDeviceEx(params);

	video::IVideoDriver* driver = device->getVideoDriver();

	scene::ISceneManager* smgr = device->getSceneManager();
	driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, true);
	scene::ICameraSceneNode* camera =
		smgr->addCameraSceneNodeFPS(0, 100.0f, 0.01f);
	camera->setPosition(core::vector3df(0, 0, 3));
	camera->setTarget(core::vector3df(0, 0, 0));
	camera->setNearValue(0.01f);
	camera->setFarValue(10000.0f);
	smgr->setActiveCamera(camera);
	device->getCursorControl()->setVisible(false);
	MyEventReceiver receiver;
	device->setEventReceiver(&receiver);

	SimpleCallBack* cb = new SimpleCallBack();
	video::E_MATERIAL_TYPE newMaterialType = (video::E_MATERIAL_TYPE)driver->getGPUProgrammingServices()->addHighLevelShaderMaterialFromFiles("../mesh.vert",
		"", "", "", //! No Geometry or Tessellation Shaders
		"../mesh.frag",
		3, video::EMT_SOLID, //! 3 vertices per primitive (this is tessellation shader relevant only
		cb, //! Our Shader Callback
		0); //! No custom user data
	cb->drop();

	if (device == 0)
		return 1; // could not create selected driver.

	io::IFileSystem* fs = device->getFileSystem();
	asset::IAssetManager* am = device->getAssetManager();

	am.addAssetLoader(core::make_smart_refctd_ptr<irr::ext::MitsubaLoader::CMitsubaLoader>(device));

#define MITSUBA_LOADER_TESTS

#ifdef MITSUBA_LOADER_TESTS
	std::string filePath = "../../media/mitsuba/staircase2/scene.xml";
#else
	pfd::message("Choose file to load", "Choose mitsuba XML file to load or ZIP containing an XML. \nIf you cancel or choosen file fails to load bathroom will be loaded.", pfd::choice::ok);
	pfd::open_file file("Choose XML file", "", { "XML files (.xml)", "*.xml" });
	std::string filePath = file.result().empty() ? "C:\\IrrlichtBAW\\/IrrlichtBAW\\examples_tests\\media\\mitsuba\\bathroom\\sce===
		netest.xml" : file.result()[0];
#endif
	asset::SAssetBundle meshes = am->getAsset(filePath, {});

	driver->getGPUObjectsFromAssets(meshes.getContents().first, meshes.getContents().second);
	for (int i = 0; i < meshes.getSize(); i++)
	{
		meshes.getContents().first
		asset::ICPUMesh* cpumesh = static_cast<asset::ICPUMesh*>((meshes.getContents().first + i)->get());
		video::IGPUMesh* gpumesh = driver->getGPUObjectsFromAssets(&cpumesh, (&cpumesh) + 1)[0];
		smgr->addMeshSceneNode(gpumesh)->setMaterialType(newMaterialType);
		gpumesh->drop();
	}

	while (!quit && device->run())
	{
		driver->beginScene(true, true, video::SColor(255, 0, 0, 255));

		//! This animates (moves) the camera and sets the transforms
		//! Also draws the meshbuffer
		smgr->drawAll();

		driver->endScene();
	}

	device->drop();
	return 0;
}
<|endoftext|>


<commit_before>#include "stdafx.h"
#include <unittest.h>
#include <matrix.h>

void test_matrices() {

	scenario sc("Matrices Test");

	sc.pass();
}<commit_msg>[minor] Compiled which functions to test<commit_after>#include "stdafx.h"
#include <unittest.h>
#include <matrix.h>

void test_matrices() {

	scenario sc("Matrices Test");
/*
	Functions to test:
	transpose
	sum
	subtract
	multiply
	random
	+
	-
	*
	/
	*/
	sc.pass();
}<|endoftext|>


<commit_before>#define DEBUG 1
/**
 * File    : B2.cpp
 * Author  : Kazune Takahashi
 * Created : 7/22/2019, 3:04:34 AM
 * Powered by Visual Studio Code
 */
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <vector>
#include <string>
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <bitset>
#include <functional>
#include <random>
#include <chrono>
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;
#define maxs(x, y) (x = max(x, y))
#define mins(x, y) (x = min(x, y))
using ll = long long;
class mint
{
public:
  static ll MOD;
  ll x;
  mint() : x(0) {}
  mint(ll x) : x(x % MOD) {}
  mint operator-() const { return x ? MOD - x : 0; }
  mint &operator+=(const mint &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  mint &operator-=(const mint &a) { return *this += -a; }
  mint &operator*=(const mint &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  mint &operator/=(const mint &a)
  {
    mint b{a};
    return *this *= b.power(MOD - 2);
  }
  mint operator+(const mint &a) const { return mint(*this) += a; }
  mint operator-(const mint &a) const { return mint(*this) -= a; }
  mint operator*(const mint &a) const { return mint(*this) *= a; }
  mint operator/(const mint &a) const { return mint(*this) /= a; }
  bool operator<(const mint &a) const { return x < a.x; }
  bool operator==(const mint &a) const { return x == a.x; }
  const mint power(ll N)
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      mint half = power(N / 2);
      return half * half;
    }
  }
};
ll mint::MOD = 1e9 + 7;
istream &operator>>(istream &stream, mint &a) { return stream >> a.x; }
ostream &operator<<(ostream &stream, const mint &a) { return stream << a.x; }
class combination
{
public:
  vector<mint> inv, fact, factinv;
  static int MAX_SIZE;
  combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i = 2; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[mint::MOD % i]) * (mint::MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i = 1; i < MAX_SIZE; i++)
    {
      fact[i] = mint(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  mint operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
};
int combination::MAX_SIZE = 3000010;
ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; }
// constexpr double epsilon = 1e-10;
// constexpr ll infty = 1000000000000000LL;
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "No" << endl;
  exit(0);
}

ll N, K;
ll C;
int A[200010];
ll a[60][200010];

int main()
{
  cin >> N >> K;
  C = N * K;
  for (auto i = 0; i < N; i++)
  {
    cin >> A[i];
  }
  for (auto i = 0; i < N; i++)
  {
    a[i][0] = -1;
  }
  vector<int> used(200010, -1);
  for (auto k = 0; k < 2; k++)
  {
    for (auto i = 0; i < N; i++)
    {
      if (used[A[i]] != -1)
      {
        a[0][used[A[i]]] = k * N + i - used[A[i]];
      }
      used[A[i]] = k * N + i;
    }
  }
#if DEBUG == 1
  for (auto i = 0; i < N; i++)
  {
    cerr << "a[0][" << i << "] = " << a[0][i] << endl;
  }
#endif
  for (auto k = 1; k < 60; k++)
  {
    for (auto i = 0; i < N; i++)
    {
      a[k][i] = a[k - 1][i] + a[k - 1][(a[k - 1][i] + 1) % N];
#if DEBUG == 1
      if (k < 5)
      {
        cerr << "a[" << k << "][" << i << "] = " << a[k][i] << endl;
      }
#endif
    }
  }
  ll sum = 0;
  int now = 0;
  while (true)
  {
    int ind = 0;
    for (auto k = 0; k < 60; k++)
    {
      if (a[k][now] + sum > C)
      {
        ind = k - 1;
        break;
      }
    }
    if (ind == -1)
    {
      break;
    }
    sum += a[ind][now];
    now = (sum + 1) % N;
  }
#if DEBUG == 1
  cerr << "sum = " << sum << endl;
  cerr << "now = " << now << endl;
#endif
  deque<int> D;
  vector<bool> stacked(200010, false);
  for (auto i = now; i < N; i++)
  {
    if (!stacked[A[i]])
    {
      D.push_back(A[i]);
      stacked[A[i]] = true;
    }
    else
    {
      while (true)
      {
        int x = *D.rbegin();
        D.pop_back();
        stacked[x] = false;
        if (x == A[i])
        {
          break;
        }
      }
    }
  }
  for (auto i = 0u; i < D.size(); i++)
  {
    cout << D[i];
    if (i < D.size() - 1)
    {
      cout << " ";
    }
  }
  cout << endl;
}<commit_msg>tried B2.cpp to 'B'<commit_after>#define DEBUG 1
/**
 * File    : B2.cpp
 * Author  : Kazune Takahashi
 * Created : 7/22/2019, 3:04:34 AM
 * Powered by Visual Studio Code
 */
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <vector>
#include <string>
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <bitset>
#include <functional>
#include <random>
#include <chrono>
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;
#define maxs(x, y) (x = max(x, y))
#define mins(x, y) (x = min(x, y))
using ll = long long;
class mint
{
public:
  static ll MOD;
  ll x;
  mint() : x(0) {}
  mint(ll x) : x(x % MOD) {}
  mint operator-() const { return x ? MOD - x : 0; }
  mint &operator+=(const mint &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  mint &operator-=(const mint &a) { return *this += -a; }
  mint &operator*=(const mint &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  mint &operator/=(const mint &a)
  {
    mint b{a};
    return *this *= b.power(MOD - 2);
  }
  mint operator+(const mint &a) const { return mint(*this) += a; }
  mint operator-(const mint &a) const { return mint(*this) -= a; }
  mint operator*(const mint &a) const { return mint(*this) *= a; }
  mint operator/(const mint &a) const { return mint(*this) /= a; }
  bool operator<(const mint &a) const { return x < a.x; }
  bool operator==(const mint &a) const { return x == a.x; }
  const mint power(ll N)
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      mint half = power(N / 2);
      return half * half;
    }
  }
};
ll mint::MOD = 1e9 + 7;
istream &operator>>(istream &stream, mint &a) { return stream >> a.x; }
ostream &operator<<(ostream &stream, const mint &a) { return stream << a.x; }
class combination
{
public:
  vector<mint> inv, fact, factinv;
  static int MAX_SIZE;
  combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i = 2; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[mint::MOD % i]) * (mint::MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i = 1; i < MAX_SIZE; i++)
    {
      fact[i] = mint(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  mint operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
};
int combination::MAX_SIZE = 3000010;
ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; }
// constexpr double epsilon = 1e-10;
// constexpr ll infty = 1000000000000000LL;
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "No" << endl;
  exit(0);
}

ll N, K;
ll C;
int A[200010];
ll a[60][200010];

int main()
{
  cin >> N >> K;
  C = N * K;
  for (auto i = 0; i < N; i++)
  {
    cin >> A[i];
  }
  for (auto i = 0; i < N; i++)
  {
    a[i][0] = -1;
  }
  vector<int> used(200010, -1);
  for (auto k = 0; k < 2; k++)
  {
    for (auto i = 0; i < N; i++)
    {
      if (used[A[i]] != -1)
      {
        a[0][used[A[i]]] = k * N + i - used[A[i]];
      }
      used[A[i]] = k * N + i;
    }
  }
#if DEBUG == 1
  for (auto i = 0; i < N; i++)
  {
    cerr << "a[0][" << i << "] = " << a[0][i] << endl;
  }
#endif
  for (auto k = 1; k < 60; k++)
  {
    for (auto i = 0; i < N; i++)
    {
      a[k][i] = a[k - 1][i] + a[k - 1][(a[k - 1][i] + 1) % N] + 1;
#if DEBUG == 1
      if (k < 5)
      {
        cerr << "a[" << k << "][" << i << "] = " << a[k][i] << endl;
      }
#endif
    }
  }
  ll sum = 0;
  int now = 0;
  while (true)
  {
    int ind = 0;
    for (auto k = 0; k < 60; k++)
    {
      if (a[k][now] + sum > C)
      {
        ind = k - 1;
        break;
      }
    }
    if (ind == -1)
    {
      break;
    }
    sum += a[ind][now];
    now = (sum + 1) % N;
  }
#if DEBUG == 1
  cerr << "sum = " << sum << endl;
  cerr << "now = " << now << endl;
#endif
  deque<int> D;
  vector<bool> stacked(200010, false);
  for (auto i = now; i < N; i++)
  {
    if (!stacked[A[i]])
    {
      D.push_back(A[i]);
      stacked[A[i]] = true;
    }
    else
    {
      while (true)
      {
        int x = *D.rbegin();
        D.pop_back();
        stacked[x] = false;
        if (x == A[i])
        {
          break;
        }
      }
    }
  }
  for (auto i = 0u; i < D.size(); i++)
  {
    cout << D[i];
    if (i < D.size() - 1)
    {
      cout << " ";
    }
  }
  cout << endl;
}<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
 *
 * 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.
 *
 */

// CLASS HEADER
#include "native-image-source-impl.h"

// EXTERNAL INCLUDES
#include <dali/integration-api/debug.h>
#include <dali/integration-api/gl-defines.h>
#include <cstring>

// INTERNAL INCLUDES
#include <gl/egl-image-extensions.h>
#include <gl/egl-factory.h>
#include <adaptor-impl.h>
#include <render-surface.h>

// Allow this to be encoded and saved:
#include <platform-abstractions/tizen/resource-loader/resource-loader.h>
#include <bitmap-saver.h>

namespace Dali
{

namespace Internal
{

namespace Adaptor
{

namespace
{
const char* FRAGMENT_PREFIX = "#extension GL_OES_EGL_image_external:require\n";
const char* SAMPLER_TYPE = "samplerExternalOES";

tbm_format FORMATS_BLENDING_REQUIRED[] = {
  TBM_FORMAT_ARGB4444, TBM_FORMAT_ABGR4444,
  TBM_FORMAT_RGBA4444, TBM_FORMAT_BGRA4444,
  TBM_FORMAT_RGBX5551, TBM_FORMAT_BGRX5551,
  TBM_FORMAT_ARGB1555, TBM_FORMAT_ABGR1555,
  TBM_FORMAT_RGBA5551, TBM_FORMAT_BGRA5551,
  TBM_FORMAT_ARGB8888, TBM_FORMAT_ABGR8888,
  TBM_FORMAT_RGBA8888, TBM_FORMAT_BGRA8888,
  TBM_FORMAT_ARGB2101010, TBM_FORMAT_ABGR2101010,
  TBM_FORMAT_RGBA1010102, TBM_FORMAT_BGRA1010102
};

const int NUM_FORMATS_BLENDING_REQUIRED = 18;

}

using Dali::Integration::PixelBuffer;

NativeImageSource* NativeImageSource::New(unsigned int width, unsigned int height, Dali::NativeImageSource::ColorDepth depth, Any nativeImageSource )
{
  NativeImageSource* image = new NativeImageSource( width, height, depth, nativeImageSource );
  DALI_ASSERT_DEBUG( image && "NativeImageSource allocation failed." );

  if( image )
  {
    image->Initialize();
  }

  return image;
}

NativeImageSource::NativeImageSource( unsigned int width, unsigned int height, Dali::NativeImageSource::ColorDepth depth, Any nativeImageSource )
: mWidth( width ),
  mHeight( height ),
  mOwnTbmSurface( false ),
  mTbmSurface( NULL ),
  mTbmFormat( 0 ),
  mBlendingRequired( false ),
  mColorDepth( depth ),
  mEglImageKHR( NULL ),
  mEglImageExtensions( NULL ),
  mSetSource( false )
{
  DALI_ASSERT_ALWAYS( Adaptor::IsAvailable() );
  EglFactory& eglFactory = Adaptor::GetImplementation( Adaptor::Get() ).GetEGLFactory();
  mEglImageExtensions = eglFactory.GetImageExtensions();
  DALI_ASSERT_DEBUG( mEglImageExtensions );

  mTbmSurface = GetSurfaceFromAny( nativeImageSource );

  if( mTbmSurface != NULL )
  {
    mBlendingRequired = CheckBlending( tbm_surface_get_format( mTbmSurface ) );
    mWidth = tbm_surface_get_width( mTbmSurface );
    mHeight = tbm_surface_get_height( mTbmSurface );
  }
}

void NativeImageSource::Initialize()
{
  if( mTbmSurface != NULL || mWidth == 0 || mHeight == 0 )
  {
    return;
  }

  tbm_format format = TBM_FORMAT_RGB888;
  int depth = 0;

  switch( mColorDepth )
  {
    case Dali::NativeImageSource::COLOR_DEPTH_DEFAULT:
    {
      format = TBM_FORMAT_RGBA8888;
      depth = 32;
      break;
    }
    case Dali::NativeImageSource::COLOR_DEPTH_8:
    {
      format = TBM_FORMAT_C8;
      depth = 8;
      break;
    }
    case Dali::NativeImageSource::COLOR_DEPTH_16:
    {
      format = TBM_FORMAT_RGB565;
      depth = 16;
      break;
    }
    case Dali::NativeImageSource::COLOR_DEPTH_24:
    {
      format = TBM_FORMAT_RGB888;
      depth = 24;
      break;
    }
    case Dali::NativeImageSource::COLOR_DEPTH_32:
    {
      format = TBM_FORMAT_RGBA8888;
      depth = 32;
      break;
    }
    default:
    {
      DALI_LOG_WARNING( "Wrong color depth.\n" );
      return;
    }
  }

  // set whether blending is required according to pixel format based on the depth
  /* default pixel format is RGB888
     If depth = 8, Pixel::A8;
     If depth = 16, Pixel::RGB565;
     If depth = 32, Pixel::RGBA8888 */
  mBlendingRequired = ( depth == 32 || depth == 8 );

  mTbmSurface = tbm_surface_create( mWidth, mHeight, format );
  mOwnTbmSurface = true;
}

tbm_surface_h NativeImageSource::GetSurfaceFromAny( Any source ) const
{
  if( source.Empty() )
  {
    return NULL;
  }

  if( source.GetType() == typeid( tbm_surface_h ) )
  {
    return AnyCast< tbm_surface_h >( source );
  }
  else
  {
    return NULL;
  }
}

NativeImageSource::~NativeImageSource()
{
  if( mOwnTbmSurface && mTbmSurface != NULL )
  {
    if( tbm_surface_destroy( mTbmSurface ) != TBM_SURFACE_ERROR_NONE )
    {
      DALI_LOG_ERROR( "Failed to destroy tbm_surface\n" );
    }
  }
}

Any NativeImageSource::GetNativeImageSource() const
{
  return Any( mTbmSurface );
}

bool NativeImageSource::GetPixels(std::vector<unsigned char>& pixbuf, unsigned& width, unsigned& height, Pixel::Format& pixelFormat) const
{
  if( mTbmSurface != NULL )
  {
    tbm_surface_info_s surface_info;

    if( tbm_surface_map( mTbmSurface, TBM_SURF_OPTION_READ, &surface_info) != TBM_SURFACE_ERROR_NONE )
    {
      DALI_LOG_ERROR( "Fail to map tbm_surface\n" );

      width = 0;
      height = 0;

      return false;
    }

    tbm_format format = surface_info.format;
    uint32_t stride = surface_info.planes[0].stride;
    unsigned char* ptr = surface_info.planes[0].ptr;

    width = mWidth;
    height = mHeight;
    size_t lineSize;
    size_t offset;
    size_t cOffset;

    switch( format )
    {
      case TBM_FORMAT_RGB888:
      {
        lineSize = width*3;
        pixelFormat = Pixel::RGB888;
        pixbuf.resize( lineSize*height );
        unsigned char* bufptr = &pixbuf[0];

        for( unsigned int r = 0; r < height; ++r, bufptr += lineSize )
        {
          for( unsigned int c = 0; c < width; ++c )
          {
            cOffset = c*3;
            offset = cOffset + r*stride;
            *(bufptr) = ptr[offset+2];
            *(bufptr+cOffset+1) = ptr[offset+1];
            *(bufptr+cOffset+2) = ptr[offset];
          }
        }
        break;
      }
      case TBM_FORMAT_RGBA8888:
      {
        lineSize = width*4;
        pixelFormat = Pixel::RGBA8888;
        pixbuf.resize( lineSize*height );
        unsigned char* bufptr = &pixbuf[0];

        for( unsigned int r = 0; r < height; ++r, bufptr += lineSize )
        {
          for( unsigned int c = 0; c < width; ++c )
          {
            cOffset = c*4;
            offset = cOffset + r*stride;
            *(bufptr) = ptr[offset+3];
            *(bufptr+cOffset+1) = ptr[offset+2];
            *(bufptr+cOffset+2) = ptr[offset+1];
            *(bufptr+cOffset+3) = ptr[offset];
          }
        }
        break;
      }
      default:
      {
        DALI_LOG_WARNING( "Tbm surface has unsupported pixel format.\n" );

        pixbuf.resize( 0 );
        width = 0;
        height = 0;

        return false;
      }
    }

    if( tbm_surface_unmap( mTbmSurface ) != TBM_SURFACE_ERROR_NONE )
    {
      DALI_LOG_ERROR( "Fail to unmap tbm_surface\n" );
    }

    return true;
  }

  DALI_LOG_WARNING( "TBM surface does not exist.\n" );

  width = 0;
  height = 0;

  return false;
}

bool NativeImageSource::EncodeToFile(const std::string& filename) const
{
  std::vector< unsigned char > pixbuf;
  unsigned int width(0), height(0);
  Pixel::Format pixelFormat;

  if(GetPixels(pixbuf, width, height, pixelFormat))
  {
    return Dali::EncodeToFile(&pixbuf[0], filename, pixelFormat, width, height);
  }
  return false;
}

void NativeImageSource::SetSource( Any source )
{
  if( mOwnTbmSurface && mTbmSurface != NULL )
  {
    if( tbm_surface_destroy( mTbmSurface ) != TBM_SURFACE_ERROR_NONE )
    {
      DALI_LOG_ERROR( "Failed to destroy tbm_surface\n" );
    }

    mTbmSurface = NULL;
    mOwnTbmSurface = false;
  }

  mTbmSurface = GetSurfaceFromAny( source );
  mSetSource = true;

  if( mTbmSurface != NULL )
  {
    mBlendingRequired = CheckBlending( tbm_surface_get_format( mTbmSurface ) );
    mWidth = tbm_surface_get_width( mTbmSurface );
    mHeight = tbm_surface_get_height( mTbmSurface );
  }
}

bool NativeImageSource::IsColorDepthSupported( Dali::NativeImageSource::ColorDepth colorDepth )
{
  uint32_t* formats;
  uint32_t formatNum;
  tbm_format format = TBM_FORMAT_RGB888;

  switch( colorDepth )
  {
    case Dali::NativeImageSource::COLOR_DEPTH_DEFAULT:
    {
      format = TBM_FORMAT_RGBA8888;
      break;
    }
    case Dali::NativeImageSource::COLOR_DEPTH_8:
    {
      format = TBM_FORMAT_C8;
      break;
    }
    case Dali::NativeImageSource::COLOR_DEPTH_16:
    {
      format = TBM_FORMAT_RGB565;
      break;
    }
    case Dali::NativeImageSource::COLOR_DEPTH_24:
    {
      format = TBM_FORMAT_RGB888;
      break;
    }
    case Dali::NativeImageSource::COLOR_DEPTH_32:
    {
      format = TBM_FORMAT_RGBA8888;
      break;
    }
  }

  if( tbm_surface_query_formats( &formats, &formatNum ) )
  {
    for( unsigned int i = 0; i < formatNum; i++ )
    {
      if( formats[i] == format )
      {
        free( formats );
        return true;
      }
    }
  }

  free( formats );
  return false;
}

bool NativeImageSource::GlExtensionCreate()
{
  // casting from an unsigned int to a void *, which should then be cast back
  // to an unsigned int in the driver.
  EGLClientBuffer eglBuffer = reinterpret_cast< EGLClientBuffer >(mTbmSurface);
  if( !eglBuffer )
  {
    return false;
  }

  mEglImageKHR = mEglImageExtensions->CreateImageKHR( eglBuffer );

  return mEglImageKHR != NULL;
}

void NativeImageSource::GlExtensionDestroy()
{
  if( mEglImageKHR )
  {
    mEglImageExtensions->DestroyImageKHR(mEglImageKHR);

    mEglImageKHR = NULL;
  }
}

unsigned int NativeImageSource::TargetTexture()
{
  mEglImageExtensions->TargetTextureKHR(mEglImageKHR);

  return 0;
}

void NativeImageSource::PrepareTexture()
{
  if( mSetSource )
  {
    void* eglImage = mEglImageKHR;

    if( GlExtensionCreate() )
    {
      TargetTexture();
    }

    mEglImageExtensions->DestroyImageKHR( eglImage );

    mSetSource = false;
  }
}

int NativeImageSource::GetPixelDepth(Dali::NativeImageSource::ColorDepth depth) const
{
  switch (depth)
  {
    case Dali::NativeImageSource::COLOR_DEPTH_DEFAULT:
    {
      // ToDo: Get the default screen depth
      return 32;
    }
    case Dali::NativeImageSource::COLOR_DEPTH_8:
    {
      return 8;
    }
    case Dali::NativeImageSource::COLOR_DEPTH_16:
    {
      return 16;
    }
    case Dali::NativeImageSource::COLOR_DEPTH_24:
    {
      return 24;
    }
    case Dali::NativeImageSource::COLOR_DEPTH_32:
    {
      return 32;
    }
    default:
    {
      DALI_ASSERT_DEBUG(0 && "unknown color enum");
      return 0;
    }
  }
}

const char* NativeImageSource::GetCustomFragmentPreFix()
{
  return FRAGMENT_PREFIX;
}

const char* NativeImageSource::GetCustomSamplerTypename()
{
  return SAMPLER_TYPE;
}

int NativeImageSource::GetEglImageTextureTarget()
{
  return GL_TEXTURE_EXTERNAL_OES;
}

bool NativeImageSource::CheckBlending( tbm_format format )
{
  if( mTbmFormat != format )
  {
    for(int i = 0; i < NUM_FORMATS_BLENDING_REQUIRED; ++i)
    {
      if( format == FORMATS_BLENDING_REQUIRED[i] )
      {
        mBlendingRequired = true;
        break;
      }
    }
    mTbmFormat = format;
  }

  return mBlendingRequired;
}

} // namespace Adaptor

} // namespace internal

} // namespace Dali
<commit_msg>Added ref/unref tbm_surface<commit_after>/*
 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
 *
 * 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.
 *
 */

// CLASS HEADER
#include "native-image-source-impl.h"

// EXTERNAL INCLUDES
#include <dali/integration-api/debug.h>
#include <dali/integration-api/gl-defines.h>
#include <cstring>
#include <tbm_surface_internal.h>

// INTERNAL INCLUDES
#include <gl/egl-image-extensions.h>
#include <gl/egl-factory.h>
#include <adaptor-impl.h>
#include <render-surface.h>

// Allow this to be encoded and saved:
#include <platform-abstractions/tizen/resource-loader/resource-loader.h>
#include <bitmap-saver.h>

namespace Dali
{

namespace Internal
{

namespace Adaptor
{

namespace
{
const char* FRAGMENT_PREFIX = "#extension GL_OES_EGL_image_external:require\n";
const char* SAMPLER_TYPE = "samplerExternalOES";

tbm_format FORMATS_BLENDING_REQUIRED[] = {
  TBM_FORMAT_ARGB4444, TBM_FORMAT_ABGR4444,
  TBM_FORMAT_RGBA4444, TBM_FORMAT_BGRA4444,
  TBM_FORMAT_RGBX5551, TBM_FORMAT_BGRX5551,
  TBM_FORMAT_ARGB1555, TBM_FORMAT_ABGR1555,
  TBM_FORMAT_RGBA5551, TBM_FORMAT_BGRA5551,
  TBM_FORMAT_ARGB8888, TBM_FORMAT_ABGR8888,
  TBM_FORMAT_RGBA8888, TBM_FORMAT_BGRA8888,
  TBM_FORMAT_ARGB2101010, TBM_FORMAT_ABGR2101010,
  TBM_FORMAT_RGBA1010102, TBM_FORMAT_BGRA1010102
};

const int NUM_FORMATS_BLENDING_REQUIRED = 18;

}

using Dali::Integration::PixelBuffer;

NativeImageSource* NativeImageSource::New(unsigned int width, unsigned int height, Dali::NativeImageSource::ColorDepth depth, Any nativeImageSource )
{
  NativeImageSource* image = new NativeImageSource( width, height, depth, nativeImageSource );
  DALI_ASSERT_DEBUG( image && "NativeImageSource allocation failed." );

  if( image )
  {
    image->Initialize();
  }

  return image;
}

NativeImageSource::NativeImageSource( unsigned int width, unsigned int height, Dali::NativeImageSource::ColorDepth depth, Any nativeImageSource )
: mWidth( width ),
  mHeight( height ),
  mOwnTbmSurface( false ),
  mTbmSurface( NULL ),
  mTbmFormat( 0 ),
  mBlendingRequired( false ),
  mColorDepth( depth ),
  mEglImageKHR( NULL ),
  mEglImageExtensions( NULL ),
  mSetSource( false )
{
  DALI_ASSERT_ALWAYS( Adaptor::IsAvailable() );
  EglFactory& eglFactory = Adaptor::GetImplementation( Adaptor::Get() ).GetEGLFactory();
  mEglImageExtensions = eglFactory.GetImageExtensions();
  DALI_ASSERT_DEBUG( mEglImageExtensions );

  mTbmSurface = GetSurfaceFromAny( nativeImageSource );

  if( mTbmSurface != NULL )
  {
    tbm_surface_internal_ref( mTbmSurface );
    mBlendingRequired = CheckBlending( tbm_surface_get_format( mTbmSurface ) );
    mWidth = tbm_surface_get_width( mTbmSurface );
    mHeight = tbm_surface_get_height( mTbmSurface );
  }
}

void NativeImageSource::Initialize()
{
  if( mTbmSurface != NULL || mWidth == 0 || mHeight == 0 )
  {
    return;
  }

  tbm_format format = TBM_FORMAT_RGB888;
  int depth = 0;

  switch( mColorDepth )
  {
    case Dali::NativeImageSource::COLOR_DEPTH_DEFAULT:
    {
      format = TBM_FORMAT_RGBA8888;
      depth = 32;
      break;
    }
    case Dali::NativeImageSource::COLOR_DEPTH_8:
    {
      format = TBM_FORMAT_C8;
      depth = 8;
      break;
    }
    case Dali::NativeImageSource::COLOR_DEPTH_16:
    {
      format = TBM_FORMAT_RGB565;
      depth = 16;
      break;
    }
    case Dali::NativeImageSource::COLOR_DEPTH_24:
    {
      format = TBM_FORMAT_RGB888;
      depth = 24;
      break;
    }
    case Dali::NativeImageSource::COLOR_DEPTH_32:
    {
      format = TBM_FORMAT_RGBA8888;
      depth = 32;
      break;
    }
    default:
    {
      DALI_LOG_WARNING( "Wrong color depth.\n" );
      return;
    }
  }

  // set whether blending is required according to pixel format based on the depth
  /* default pixel format is RGB888
     If depth = 8, Pixel::A8;
     If depth = 16, Pixel::RGB565;
     If depth = 32, Pixel::RGBA8888 */
  mBlendingRequired = ( depth == 32 || depth == 8 );

  mTbmSurface = tbm_surface_create( mWidth, mHeight, format );
  mOwnTbmSurface = true;
}

tbm_surface_h NativeImageSource::GetSurfaceFromAny( Any source ) const
{
  if( source.Empty() )
  {
    return NULL;
  }

  if( source.GetType() == typeid( tbm_surface_h ) )
  {
    return AnyCast< tbm_surface_h >( source );
  }
  else
  {
    return NULL;
  }
}

NativeImageSource::~NativeImageSource()
{
  if( mOwnTbmSurface )
  {
    if( mTbmSurface != NULL && tbm_surface_destroy( mTbmSurface ) != TBM_SURFACE_ERROR_NONE )
    {
      DALI_LOG_ERROR( "Failed to destroy tbm_surface\n" );
    }
  }
  else
  {
    if( mTbmSurface != NULL )
    {
      tbm_surface_internal_unref( mTbmSurface );
    }
  }
}

Any NativeImageSource::GetNativeImageSource() const
{
  return Any( mTbmSurface );
}

bool NativeImageSource::GetPixels(std::vector<unsigned char>& pixbuf, unsigned& width, unsigned& height, Pixel::Format& pixelFormat) const
{
  if( mTbmSurface != NULL )
  {
    tbm_surface_info_s surface_info;

    if( tbm_surface_map( mTbmSurface, TBM_SURF_OPTION_READ, &surface_info) != TBM_SURFACE_ERROR_NONE )
    {
      DALI_LOG_ERROR( "Fail to map tbm_surface\n" );

      width = 0;
      height = 0;

      return false;
    }

    tbm_format format = surface_info.format;
    uint32_t stride = surface_info.planes[0].stride;
    unsigned char* ptr = surface_info.planes[0].ptr;

    width = mWidth;
    height = mHeight;
    size_t lineSize;
    size_t offset;
    size_t cOffset;

    switch( format )
    {
      case TBM_FORMAT_RGB888:
      {
        lineSize = width*3;
        pixelFormat = Pixel::RGB888;
        pixbuf.resize( lineSize*height );
        unsigned char* bufptr = &pixbuf[0];

        for( unsigned int r = 0; r < height; ++r, bufptr += lineSize )
        {
          for( unsigned int c = 0; c < width; ++c )
          {
            cOffset = c*3;
            offset = cOffset + r*stride;
            *(bufptr) = ptr[offset+2];
            *(bufptr+cOffset+1) = ptr[offset+1];
            *(bufptr+cOffset+2) = ptr[offset];
          }
        }
        break;
      }
      case TBM_FORMAT_RGBA8888:
      {
        lineSize = width*4;
        pixelFormat = Pixel::RGBA8888;
        pixbuf.resize( lineSize*height );
        unsigned char* bufptr = &pixbuf[0];

        for( unsigned int r = 0; r < height; ++r, bufptr += lineSize )
        {
          for( unsigned int c = 0; c < width; ++c )
          {
            cOffset = c*4;
            offset = cOffset + r*stride;
            *(bufptr) = ptr[offset+3];
            *(bufptr+cOffset+1) = ptr[offset+2];
            *(bufptr+cOffset+2) = ptr[offset+1];
            *(bufptr+cOffset+3) = ptr[offset];
          }
        }
        break;
      }
      default:
      {
        DALI_LOG_WARNING( "Tbm surface has unsupported pixel format.\n" );

        pixbuf.resize( 0 );
        width = 0;
        height = 0;

        return false;
      }
    }

    if( tbm_surface_unmap( mTbmSurface ) != TBM_SURFACE_ERROR_NONE )
    {
      DALI_LOG_ERROR( "Fail to unmap tbm_surface\n" );
    }

    return true;
  }

  DALI_LOG_WARNING( "TBM surface does not exist.\n" );

  width = 0;
  height = 0;

  return false;
}

bool NativeImageSource::EncodeToFile(const std::string& filename) const
{
  std::vector< unsigned char > pixbuf;
  unsigned int width(0), height(0);
  Pixel::Format pixelFormat;

  if(GetPixels(pixbuf, width, height, pixelFormat))
  {
    return Dali::EncodeToFile(&pixbuf[0], filename, pixelFormat, width, height);
  }
  return false;
}

void NativeImageSource::SetSource( Any source )
{
  if( mOwnTbmSurface )
  {
    if( mTbmSurface != NULL && tbm_surface_destroy( mTbmSurface ) != TBM_SURFACE_ERROR_NONE )
    {
      DALI_LOG_ERROR( "Failed to destroy tbm_surface\n" );
    }

    mTbmSurface = NULL;
    mOwnTbmSurface = false;
  }
  else
  {
    if( mTbmSurface != NULL )
    {
      tbm_surface_internal_unref( mTbmSurface );
      mTbmSurface = NULL;
    }
  }

  mTbmSurface = GetSurfaceFromAny( source );

  if( mTbmSurface != NULL )
  {
    mSetSource = true;
    tbm_surface_internal_ref( mTbmSurface );
    mBlendingRequired = CheckBlending( tbm_surface_get_format( mTbmSurface ) );
    mWidth = tbm_surface_get_width( mTbmSurface );
    mHeight = tbm_surface_get_height( mTbmSurface );
  }
}

bool NativeImageSource::IsColorDepthSupported( Dali::NativeImageSource::ColorDepth colorDepth )
{
  uint32_t* formats;
  uint32_t formatNum;
  tbm_format format = TBM_FORMAT_RGB888;

  switch( colorDepth )
  {
    case Dali::NativeImageSource::COLOR_DEPTH_DEFAULT:
    {
      format = TBM_FORMAT_RGBA8888;
      break;
    }
    case Dali::NativeImageSource::COLOR_DEPTH_8:
    {
      format = TBM_FORMAT_C8;
      break;
    }
    case Dali::NativeImageSource::COLOR_DEPTH_16:
    {
      format = TBM_FORMAT_RGB565;
      break;
    }
    case Dali::NativeImageSource::COLOR_DEPTH_24:
    {
      format = TBM_FORMAT_RGB888;
      break;
    }
    case Dali::NativeImageSource::COLOR_DEPTH_32:
    {
      format = TBM_FORMAT_RGBA8888;
      break;
    }
  }

  if( tbm_surface_query_formats( &formats, &formatNum ) )
  {
    for( unsigned int i = 0; i < formatNum; i++ )
    {
      if( formats[i] == format )
      {
        free( formats );
        return true;
      }
    }
  }

  free( formats );
  return false;
}

bool NativeImageSource::GlExtensionCreate()
{
  // casting from an unsigned int to a void *, which should then be cast back
  // to an unsigned int in the driver.
  EGLClientBuffer eglBuffer = reinterpret_cast< EGLClientBuffer >(mTbmSurface);
  if( !eglBuffer )
  {
    return false;
  }

  mEglImageKHR = mEglImageExtensions->CreateImageKHR( eglBuffer );

  return mEglImageKHR != NULL;
}

void NativeImageSource::GlExtensionDestroy()
{
  if( mEglImageKHR )
  {
    mEglImageExtensions->DestroyImageKHR(mEglImageKHR);

    mEglImageKHR = NULL;
  }
}

unsigned int NativeImageSource::TargetTexture()
{
  mEglImageExtensions->TargetTextureKHR(mEglImageKHR);

  return 0;
}

void NativeImageSource::PrepareTexture()
{
  if( mSetSource )
  {
    void* eglImage = mEglImageKHR;

    if( GlExtensionCreate() )
    {
      TargetTexture();
    }

    mEglImageExtensions->DestroyImageKHR( eglImage );

    mSetSource = false;
  }
}

int NativeImageSource::GetPixelDepth(Dali::NativeImageSource::ColorDepth depth) const
{
  switch (depth)
  {
    case Dali::NativeImageSource::COLOR_DEPTH_DEFAULT:
    {
      // ToDo: Get the default screen depth
      return 32;
    }
    case Dali::NativeImageSource::COLOR_DEPTH_8:
    {
      return 8;
    }
    case Dali::NativeImageSource::COLOR_DEPTH_16:
    {
      return 16;
    }
    case Dali::NativeImageSource::COLOR_DEPTH_24:
    {
      return 24;
    }
    case Dali::NativeImageSource::COLOR_DEPTH_32:
    {
      return 32;
    }
    default:
    {
      DALI_ASSERT_DEBUG(0 && "unknown color enum");
      return 0;
    }
  }
}

const char* NativeImageSource::GetCustomFragmentPreFix()
{
  return FRAGMENT_PREFIX;
}

const char* NativeImageSource::GetCustomSamplerTypename()
{
  return SAMPLER_TYPE;
}

int NativeImageSource::GetEglImageTextureTarget()
{
  return GL_TEXTURE_EXTERNAL_OES;
}

bool NativeImageSource::CheckBlending( tbm_format format )
{
  if( mTbmFormat != format )
  {
    for(int i = 0; i < NUM_FORMATS_BLENDING_REQUIRED; ++i)
    {
      if( format == FORMATS_BLENDING_REQUIRED[i] )
      {
        mBlendingRequired = true;
        break;
      }
    }
    mTbmFormat = format;
  }

  return mBlendingRequired;
}

} // namespace Adaptor

} // namespace internal

} // namespace Dali
<|endoftext|>


<commit_before>//===- lib/ReaderWriter/ELF/Reader.cpp ------------------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief Defines the ELF Reader and all helper sub classes to consume an ELF
/// file and produces atoms out of it.
///
//===----------------------------------------------------------------------===//

#include "lld/ReaderWriter/Reader.h"

#include "Atoms.h"
#include "CreateELF.h"
#include "DynamicFile.h"
#include "File.h"

#include "lld/Core/Reference.h"
#include "lld/ReaderWriter/ELFTargetInfo.h"
#include "lld/ReaderWriter/ReaderArchive.h"

#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Object/ELF.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Memory.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/system_error.h"

#include <map>
#include <vector>

using llvm::support::endianness;
using namespace llvm::object;

namespace {
struct DynamicFileCreateELFTraits {
  typedef llvm::ErrorOr<std::unique_ptr<lld::SharedLibraryFile>> result_type;

  template <class ELFT>
  static result_type create(const lld::ELFTargetInfo &ti,
                            std::unique_ptr<llvm::MemoryBuffer> mb) {
    return lld::elf::DynamicFile<ELFT>::create(ti, std::move(mb));
  }
};

struct ELFFileCreateELFTraits {
  typedef std::unique_ptr<lld::File> result_type;

  template <class ELFT>
  static result_type create(const lld::ELFTargetInfo &ti,
                            std::unique_ptr<llvm::MemoryBuffer> mb,
                            lld::error_code &ec) {
    return std::unique_ptr<lld::File>(
        new lld::elf::ELFFile<ELFT>(ti, std::move(mb), ec));
  }
};
}

namespace lld {
namespace elf {
/// \brief A reader object that will instantiate correct File by examining the
/// memory buffer for ELF class and bit width
class ELFReader : public Reader {
public:
  ELFReader(const ELFTargetInfo &ti)
      : lld::Reader(ti), _elfTargetInfo(ti), _readerArchive(ti, *this) {
  }

  error_code parseFile(std::unique_ptr<MemoryBuffer> &mb,
                       std::vector<std::unique_ptr<File> > &result) const {
    using llvm::object::ELFType;
    llvm::sys::LLVMFileType fileType =
        llvm::sys::IdentifyFileType(mb->getBufferStart(),
                                    static_cast<unsigned>(mb->getBufferSize()));

    std::size_t MaxAlignment =
        1ULL << llvm::countTrailingZeros(uintptr_t(mb->getBufferStart()));

    llvm::error_code ec;
    switch (fileType) {
    case llvm::sys::ELF_Relocatable_FileType: {
      std::unique_ptr<File> f(createELF<ELFFileCreateELFTraits>(
          getElfArchType(&*mb), MaxAlignment, _elfTargetInfo, std::move(mb),
          ec));
      if (ec)
        return ec;
      result.push_back(std::move(f));
      break;
    }
    case llvm::sys::ELF_SharedObject_FileType: {
      auto f = createELF<DynamicFileCreateELFTraits>(
          getElfArchType(&*mb), MaxAlignment, _elfTargetInfo, std::move(mb));
      if (!f)
        return f;
      result.push_back(std::move(*f));
      break;
    }
    case llvm::sys::Archive_FileType:
      ec = _readerArchive.parseFile(mb, result);
      break;
    default:
      return llvm::make_error_code(llvm::errc::executable_format_error);
      break;
    }

    if (ec)
      return ec;

    return error_code::success();
  }

private:
  const ELFTargetInfo &_elfTargetInfo;
  ReaderArchive _readerArchive;
};
} // end namespace elf

std::unique_ptr<Reader> createReaderELF(const ELFTargetInfo &targetinfo) {
  return std::unique_ptr<Reader>(new elf::ELFReader(targetinfo));
}
} // end namespace lld
<commit_msg>Use the StringRef version of identifyFileType.<commit_after>//===- lib/ReaderWriter/ELF/Reader.cpp ------------------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief Defines the ELF Reader and all helper sub classes to consume an ELF
/// file and produces atoms out of it.
///
//===----------------------------------------------------------------------===//

#include "lld/ReaderWriter/Reader.h"

#include "Atoms.h"
#include "CreateELF.h"
#include "DynamicFile.h"
#include "File.h"

#include "lld/Core/Reference.h"
#include "lld/ReaderWriter/ELFTargetInfo.h"
#include "lld/ReaderWriter/ReaderArchive.h"

#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Object/ELF.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Memory.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/system_error.h"

#include <map>
#include <vector>

using llvm::support::endianness;
using namespace llvm::object;

namespace {
struct DynamicFileCreateELFTraits {
  typedef llvm::ErrorOr<std::unique_ptr<lld::SharedLibraryFile>> result_type;

  template <class ELFT>
  static result_type create(const lld::ELFTargetInfo &ti,
                            std::unique_ptr<llvm::MemoryBuffer> mb) {
    return lld::elf::DynamicFile<ELFT>::create(ti, std::move(mb));
  }
};

struct ELFFileCreateELFTraits {
  typedef std::unique_ptr<lld::File> result_type;

  template <class ELFT>
  static result_type create(const lld::ELFTargetInfo &ti,
                            std::unique_ptr<llvm::MemoryBuffer> mb,
                            lld::error_code &ec) {
    return std::unique_ptr<lld::File>(
        new lld::elf::ELFFile<ELFT>(ti, std::move(mb), ec));
  }
};
}

namespace lld {
namespace elf {
/// \brief A reader object that will instantiate correct File by examining the
/// memory buffer for ELF class and bit width
class ELFReader : public Reader {
public:
  ELFReader(const ELFTargetInfo &ti)
      : lld::Reader(ti), _elfTargetInfo(ti), _readerArchive(ti, *this) {
  }

  error_code parseFile(std::unique_ptr<MemoryBuffer> &mb,
                       std::vector<std::unique_ptr<File> > &result) const {
    using llvm::object::ELFType;
    llvm::sys::LLVMFileType fileType =
        llvm::sys::identifyFileType(mb->getBuffer());

    std::size_t MaxAlignment =
        1ULL << llvm::countTrailingZeros(uintptr_t(mb->getBufferStart()));

    llvm::error_code ec;
    switch (fileType) {
    case llvm::sys::ELF_Relocatable_FileType: {
      std::unique_ptr<File> f(createELF<ELFFileCreateELFTraits>(
          getElfArchType(&*mb), MaxAlignment, _elfTargetInfo, std::move(mb),
          ec));
      if (ec)
        return ec;
      result.push_back(std::move(f));
      break;
    }
    case llvm::sys::ELF_SharedObject_FileType: {
      auto f = createELF<DynamicFileCreateELFTraits>(
          getElfArchType(&*mb), MaxAlignment, _elfTargetInfo, std::move(mb));
      if (!f)
        return f;
      result.push_back(std::move(*f));
      break;
    }
    case llvm::sys::Archive_FileType:
      ec = _readerArchive.parseFile(mb, result);
      break;
    default:
      return llvm::make_error_code(llvm::errc::executable_format_error);
      break;
    }

    if (ec)
      return ec;

    return error_code::success();
  }

private:
  const ELFTargetInfo &_elfTargetInfo;
  ReaderArchive _readerArchive;
};
} // end namespace elf

std::unique_ptr<Reader> createReaderELF(const ELFTargetInfo &targetinfo) {
  return std::unique_ptr<Reader>(new elf::ELFReader(targetinfo));
}
} // end namespace lld
<|endoftext|>