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

#ifndef UNITS_HPP
#define UNITS_HPP

#include <cstddef>
#include <ratio>
#include <type_traits>
#include <utility>

namespace detail
{
#pragma mark - Sequence type
	// (integer_sequence only works with integers, not enums)

	template<typename T, T... S>
	struct sequence
	{
		using value_type = T;
		static constexpr size_t size = sizeof...(S);
	};

#pragma mark - Test if a sequence contains a value
	template<typename IntegerType, IntegerType I, IntegerType... S>
	struct sequence_contains_type;

	template<typename IntegerType, IntegerType I, IntegerType S1,
		IntegerType... Ss>
	struct sequence_contains_type<IntegerType, I, S1, Ss...>
	: std::conditional_t<I == S1,
		std::true_type,
		typename sequence_contains_type<IntegerType, I, Ss...>::type>
	{
	};

	template<typename IntegerType, IntegerType I>
	struct sequence_contains_type<IntegerType, I> : std::false_type
	{
	};

	template<typename IntegerType, IntegerType I, IntegerType... Is>
	constexpr bool sequence_contains(sequence<IntegerType, Is...>)
	{
		return sequence_contains_type<IntegerType, I, Is...>::value;
	}

#pragma mark - Combine sequences
	template<typename Seq1, typename Seq2>
	struct combine_;

	template<typename IntegerType, IntegerType... S1, IntegerType... S2>
	struct combine_<sequence<IntegerType, S1...>, sequence<IntegerType, S2...>>
	{
		using type = sequence<IntegerType, S1..., S2...>;
	};

	template<typename Seq1, typename Seq2>
	using combine = typename combine_<Seq1, Seq2>::type;

	template<typename Seq1, typename Seq2>
	constexpr auto combine_sequences(Seq1, Seq2)
	{
		return combine<Seq1, Seq2>{};
	}

#pragma mark - Remove an item
	template<typename Seq, typename IntegerType, IntegerType I>
	struct left_of_;

	template<typename IntegerType, IntegerType I>
	struct left_of_<sequence<IntegerType>, IntegerType, I>
	{
		using type = sequence<IntegerType>;
	};

	template<typename IntegerType, IntegerType I, IntegerType S1,
		IntegerType... Ss>
	struct left_of_<sequence<IntegerType, S1, Ss...>, IntegerType, I>
	{
		using type = std::conditional_t<I == S1,
			sequence<IntegerType>,
			combine<
				sequence<IntegerType, S1>,
				typename left_of_<
					sequence<IntegerType, Ss...>,
					IntegerType, I>::type>>;
	};

	template<typename Seq, typename IntegerType, IntegerType I>
	using left_of = typename left_of_<Seq, IntegerType, I>::type;

	template<typename Seq, typename IntegerType, IntegerType I>
	struct right_of_;

	template<typename IntegerType, IntegerType I>
	struct right_of_<sequence<IntegerType>, IntegerType, I>
	{
		using type = sequence<IntegerType>;
	};

	template<typename IntegerType, IntegerType I, IntegerType S1,
		IntegerType... Ss>
	struct right_of_<sequence<IntegerType, S1, Ss...>, IntegerType, I>
	{
		using type = std::conditional_t<I == S1,
			sequence<IntegerType, Ss...>,
			typename right_of_<sequence<IntegerType, Ss...>, IntegerType, I>::type
		>;
	};

	template<typename Seq, typename IntegerType, IntegerType I>
	using right_of = typename right_of_<Seq, IntegerType, I>::type;

	template<typename Seq, typename IntegerType, IntegerType I>
	struct removed_from_
	{
		using type = combine<left_of<Seq, IntegerType, I>,
		                    right_of<Seq, IntegerType, I>>;
	};
	template<typename Seq, typename IntegerType, IntegerType I>
	using removed_from = typename removed_from_<Seq, IntegerType, I>::type;

#pragma mark - Remove identical terms
	template<typename Seq1, typename Seq2>
	struct remove_intersection_;

	template<typename IntegerType1, IntegerType1... Ones, typename IntegerType2>
	struct remove_intersection_<
		sequence<IntegerType1, Ones...>,
		sequence<IntegerType2>>
	{
		using type = sequence<IntegerType1, Ones...>;
	};

	template<typename IntegerType1, IntegerType1... Ones, typename IntegerType2,
		IntegerType2 Two, IntegerType2... Twos>
	struct remove_intersection_<
		sequence<IntegerType1, Ones...>,
		sequence<IntegerType2, Two, Twos...>>
	{
		using type = removed_from<
			typename remove_intersection_<
				sequence<IntegerType1, Ones...>,
				sequence<IntegerType2, Twos...>
			>::type,
			IntegerType2, Two
		>;
	};

	template<typename Seq1, typename Seq2>
	using remove_intersection = typename remove_intersection_<Seq1, Seq2>::type;

#pragma mark - Sort a sequence
	template<typename Sequence>
	struct sequence_max;

	template<typename IntegerType, IntegerType Max>
	struct sequence_max<sequence<IntegerType, Max>>
	{
		static constexpr IntegerType value = Max;
	};

	template<typename IntegerType, IntegerType S1, IntegerType S2,
		IntegerType... Ss>
	struct sequence_max<sequence<IntegerType, S1, S2, Ss...>>
	{
		static constexpr IntegerType value = sequence_max<
			sequence<IntegerType, (S1 > S2 ? S1 : S2), Ss...>>::value;
	};

	template<typename Sequence>
	struct sorted_;

	template<typename IntegerType>
	struct sorted_<sequence<IntegerType>>
	{
		using type = sequence<IntegerType>;
	};

	template<typename IntegerType, IntegerType S1>
	struct sorted_<sequence<IntegerType, S1>>
	{
		using type = sequence<IntegerType, S1>;
	};

	template<typename IntegerType, IntegerType S1, IntegerType... Ss>
	struct sorted_<sequence<IntegerType, S1, Ss...>>
	{
	private:
		using Seq = sequence<IntegerType, S1, Ss...>;
		static constexpr IntegerType Max = sequence_max<Seq>::value;

	public:
		using type = combine<
			typename sorted_<removed_from<Seq, IntegerType, Max>>::type,
			sequence<IntegerType, Max>>;
	};

	template<typename Sequence>
	using sorted = typename sorted_<Sequence>::type;
}

namespace unitscxx
{
	template<typename NumericType, typename Numerator, typename Denominator>
	class quantity
	{
		NumericType rawValue;

	public:
		using var = quantity;
		using numerator = Numerator;
		using denominator = Denominator;
		using unit_system = typename numerator::value_type;

		static_assert(std::is_same<unit_system,
			typename denominator::value_type>::value,
			"quantity with incompatible unit systems");

		template<typename NT, typename N, typename D>
		friend class quantity;

		constexpr quantity() : rawValue{} {};
		constexpr quantity(const quantity&) = default;
		constexpr quantity(quantity&&) = default;
		quantity& operator=(const quantity&) = default;
		quantity& operator=(quantity&&) = default;

		explicit constexpr quantity(NumericType val)
			: rawValue(val)
		{
		}

		quantity& operator+=(quantity that)
		{
			return *this = *this + that;
		}

		quantity& operator-=(quantity that)
		{
			return *this = *this - that;
		}

		constexpr quantity operator+(quantity that) const
		{
			return quantity(rawValue + that.rawValue);
		}

		constexpr quantity operator-(quantity that) const
		{
			return quantity(rawValue - that.rawValue);
		}

		constexpr quantity operator+() const
		{
			return quantity(+rawValue);
		}

		constexpr quantity operator-() const
		{
			return quantity(-rawValue);
		}

		quantity& operator*=(NumericType that)
		{
			rawValue *= that;
			return *this;
		}

		quantity& operator/=(NumericType that)
		{
			rawValue /= that;
			return *this;
		}

		constexpr quantity operator*(NumericType that) const
		{
			return quantity(rawValue * that);
		}

		template<typename NT, typename N, typename D>
		constexpr auto operator*(quantity<NT, N, D> that) const
		{
			using combined_numerator   = detail::combine<numerator, N>;
			using combined_denominator = detail::combine<denominator, D>;

			using unsorted_numerator   = detail::remove_intersection<
				combined_numerator,
				combined_denominator>;

			using unsorted_denominator = detail::remove_intersection<
				combined_denominator,
				combined_numerator>;

			using result_numerator   = detail::sorted<unsorted_numerator>;
			using result_denominator = detail::sorted<unsorted_denominator>;

			using result_quantity = quantity<
				decltype(rawValue * that.rawValue),
				result_numerator,
				result_denominator>;

			return result_quantity(rawValue * that.rawValue);
		}

		constexpr quantity operator/(NumericType that) const
		{
			return quantity(rawValue / that);
		}

		template<typename NT, typename N, typename D>
		constexpr auto operator/(quantity<NT, N, D> that) const
		{
			// flip fraction rows around for division
			using combined_numerator   = detail::combine<numerator, D>;
			using combined_denominator = detail::combine<denominator, N>;

			using unsorted_numerator   = detail::remove_intersection<
				combined_numerator,
				combined_denominator>;

			using unsorted_denominator = detail::remove_intersection<
				combined_denominator,
				combined_numerator>;

			using result_numerator   = detail::sorted<unsorted_numerator>;
			using result_denominator = detail::sorted<unsorted_denominator>;

			using result_quantity = quantity<
				decltype(rawValue / that.rawValue),
				result_numerator,
				result_denominator>;

			return result_quantity(rawValue / that.rawValue);
		}

		template<intmax_t N, intmax_t D>
		constexpr quantity operator*(std::ratio<N, D>) const
		{
			return (*this) * N / D;
		}

		template<intmax_t N, intmax_t D>
		constexpr quantity operator/(std::ratio<N, D>) const
		{
			return (*this) / N * D;
		}

		template<typename N = Numerator, typename D = Denominator, typename
			= std::enable_if_t<N::size == 0 && D::size == 0>>
		constexpr operator NumericType()
		{
			return rawValue;
		}
	};

	template<typename MulType, typename NT, typename N, typename D>
	constexpr auto operator*(MulType left, quantity<NT, N, D> right)
		-> std::enable_if_t<std::is_arithmetic<MulType>::value,
			quantity<NT, N, D>>
	{
		using unit_system = typename N::value_type;
		using unitless_quantity = quantity<NT,
			detail::sequence<unit_system>,
			detail::sequence<unit_system>>;
		return unitless_quantity(left) * right;
	}

	template<typename MulType, typename NT, typename N, typename D>
	constexpr auto operator/(MulType left, quantity<NT, N, D> right)
		-> std::enable_if_t<std::is_arithmetic<MulType>::value,
			quantity<NT, D, N>>
	{
		using unit_system = typename N::value_type;
		using unitless_quantity = quantity<NT,
			detail::sequence<unit_system>,
			detail::sequence<unit_system>>;
		return unitless_quantity(left) / right;
	}

	template<intmax_t RN, intmax_t RD, typename QNT, typename QN, typename QD>
	constexpr quantity<QNT, QN, QD> operator*(
		std::ratio<RN, RD> left, quantity<QNT, QN, QD> right)
	{
		return right * left;
	}

	template<intmax_t RN, intmax_t RD, typename QNT, typename QN, typename QD>
	constexpr quantity<QNT, QD, QN> operator/(
		std::ratio<RN, RD> left, quantity<QNT, QN, QD> right)
	{
		return (1 / right) * left;
	}

	template<typename NumericType, typename UnitType, UnitType... U>
	using unit_base = quantity<NumericType,
		detail::sequence<UnitType, U...>,
		detail::sequence<UnitType>>;
}

#endif<commit_msg>get enable_if out of the return type for nice error messages like "decltype(m) d = 3*s; // error : no viable conversion from quantity<[...], sequence<[...], 2>, [...]> to quantity<[...], sequence<[...], (unitscxx::si::units)0 aka 0>, [...]>"<commit_after>//
// units.hpp
// units-cxx14
//
// Copyright (c) 2016 Félix Cloutier
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//

#ifndef UNITS_HPP
#define UNITS_HPP

#include <cstddef>
#include <ratio>
#include <type_traits>
#include <utility>

namespace detail
{
#pragma mark - Sequence type
	// (integer_sequence only works with integers, not enums)

	template<typename T, T... S>
	struct sequence
	{
		using value_type = T;
		static constexpr size_t size = sizeof...(S);
	};

#pragma mark - Test if a sequence contains a value
	template<typename IntegerType, IntegerType I, IntegerType... S>
	struct sequence_contains_type;

	template<typename IntegerType, IntegerType I, IntegerType S1,
		IntegerType... Ss>
	struct sequence_contains_type<IntegerType, I, S1, Ss...>
	: std::conditional_t<I == S1,
		std::true_type,
		typename sequence_contains_type<IntegerType, I, Ss...>::type>
	{
	};

	template<typename IntegerType, IntegerType I>
	struct sequence_contains_type<IntegerType, I> : std::false_type
	{
	};

	template<typename IntegerType, IntegerType I, IntegerType... Is>
	constexpr bool sequence_contains(sequence<IntegerType, Is...>)
	{
		return sequence_contains_type<IntegerType, I, Is...>::value;
	}

#pragma mark - Combine sequences
	template<typename Seq1, typename Seq2>
	struct combine_;

	template<typename IntegerType, IntegerType... S1, IntegerType... S2>
	struct combine_<sequence<IntegerType, S1...>, sequence<IntegerType, S2...>>
	{
		using type = sequence<IntegerType, S1..., S2...>;
	};

	template<typename Seq1, typename Seq2>
	using combine = typename combine_<Seq1, Seq2>::type;

	template<typename Seq1, typename Seq2>
	constexpr auto combine_sequences(Seq1, Seq2)
	{
		return combine<Seq1, Seq2>{};
	}

#pragma mark - Remove an item
	template<typename Seq, typename IntegerType, IntegerType I>
	struct left_of_;

	template<typename IntegerType, IntegerType I>
	struct left_of_<sequence<IntegerType>, IntegerType, I>
	{
		using type = sequence<IntegerType>;
	};

	template<typename IntegerType, IntegerType I, IntegerType S1,
		IntegerType... Ss>
	struct left_of_<sequence<IntegerType, S1, Ss...>, IntegerType, I>
	{
		using type = std::conditional_t<I == S1,
			sequence<IntegerType>,
			combine<
				sequence<IntegerType, S1>,
				typename left_of_<
					sequence<IntegerType, Ss...>,
					IntegerType, I>::type>>;
	};

	template<typename Seq, typename IntegerType, IntegerType I>
	using left_of = typename left_of_<Seq, IntegerType, I>::type;

	template<typename Seq, typename IntegerType, IntegerType I>
	struct right_of_;

	template<typename IntegerType, IntegerType I>
	struct right_of_<sequence<IntegerType>, IntegerType, I>
	{
		using type = sequence<IntegerType>;
	};

	template<typename IntegerType, IntegerType I, IntegerType S1,
		IntegerType... Ss>
	struct right_of_<sequence<IntegerType, S1, Ss...>, IntegerType, I>
	{
		using type = std::conditional_t<I == S1,
			sequence<IntegerType, Ss...>,
			typename right_of_<sequence<IntegerType, Ss...>, IntegerType, I>::type
		>;
	};

	template<typename Seq, typename IntegerType, IntegerType I>
	using right_of = typename right_of_<Seq, IntegerType, I>::type;

	template<typename Seq, typename IntegerType, IntegerType I>
	struct removed_from_
	{
		using type = combine<left_of<Seq, IntegerType, I>,
		                    right_of<Seq, IntegerType, I>>;
	};
	template<typename Seq, typename IntegerType, IntegerType I>
	using removed_from = typename removed_from_<Seq, IntegerType, I>::type;

#pragma mark - Remove identical terms
	template<typename Seq1, typename Seq2>
	struct remove_intersection_;

	template<typename IntegerType1, IntegerType1... Ones, typename IntegerType2>
	struct remove_intersection_<
		sequence<IntegerType1, Ones...>,
		sequence<IntegerType2>>
	{
		using type = sequence<IntegerType1, Ones...>;
	};

	template<typename IntegerType1, IntegerType1... Ones, typename IntegerType2,
		IntegerType2 Two, IntegerType2... Twos>
	struct remove_intersection_<
		sequence<IntegerType1, Ones...>,
		sequence<IntegerType2, Two, Twos...>>
	{
		using type = removed_from<
			typename remove_intersection_<
				sequence<IntegerType1, Ones...>,
				sequence<IntegerType2, Twos...>
			>::type,
			IntegerType2, Two
		>;
	};

	template<typename Seq1, typename Seq2>
	using remove_intersection = typename remove_intersection_<Seq1, Seq2>::type;

#pragma mark - Sort a sequence
	template<typename Sequence>
	struct sequence_max;

	template<typename IntegerType, IntegerType Max>
	struct sequence_max<sequence<IntegerType, Max>>
	{
		static constexpr IntegerType value = Max;
	};

	template<typename IntegerType, IntegerType S1, IntegerType S2,
		IntegerType... Ss>
	struct sequence_max<sequence<IntegerType, S1, S2, Ss...>>
	{
		static constexpr IntegerType value = sequence_max<
			sequence<IntegerType, (S1 > S2 ? S1 : S2), Ss...>>::value;
	};

	template<typename Sequence>
	struct sorted_;

	template<typename IntegerType>
	struct sorted_<sequence<IntegerType>>
	{
		using type = sequence<IntegerType>;
	};

	template<typename IntegerType, IntegerType S1>
	struct sorted_<sequence<IntegerType, S1>>
	{
		using type = sequence<IntegerType, S1>;
	};

	template<typename IntegerType, IntegerType S1, IntegerType... Ss>
	struct sorted_<sequence<IntegerType, S1, Ss...>>
	{
	private:
		using Seq = sequence<IntegerType, S1, Ss...>;
		static constexpr IntegerType Max = sequence_max<Seq>::value;

	public:
		using type = combine<
			typename sorted_<removed_from<Seq, IntegerType, Max>>::type,
			sequence<IntegerType, Max>>;
	};

	template<typename Sequence>
	using sorted = typename sorted_<Sequence>::type;
}

namespace unitscxx
{
	template<typename NumericType, typename Numerator, typename Denominator>
	class quantity
	{
		NumericType rawValue;

	public:
		using var = quantity;
		using numerator = Numerator;
		using denominator = Denominator;
		using unit_system = typename numerator::value_type;

		static_assert(std::is_same<unit_system,
			typename denominator::value_type>::value,
			"quantity with incompatible unit systems");

		template<typename NT, typename N, typename D>
		friend class quantity;

		constexpr quantity() : rawValue{} {};
		constexpr quantity(const quantity&) = default;
		constexpr quantity(quantity&&) = default;
		quantity& operator=(const quantity&) = default;
		quantity& operator=(quantity&&) = default;

		explicit constexpr quantity(NumericType val)
			: rawValue(val)
		{
		}

		quantity& operator+=(quantity that)
		{
			return *this = *this + that;
		}

		quantity& operator-=(quantity that)
		{
			return *this = *this - that;
		}

		constexpr quantity operator+(quantity that) const
		{
			return quantity(rawValue + that.rawValue);
		}

		constexpr quantity operator-(quantity that) const
		{
			return quantity(rawValue - that.rawValue);
		}

		constexpr quantity operator+() const
		{
			return quantity(+rawValue);
		}

		constexpr quantity operator-() const
		{
			return quantity(-rawValue);
		}

		quantity& operator*=(NumericType that)
		{
			rawValue *= that;
			return *this;
		}

		quantity& operator/=(NumericType that)
		{
			rawValue /= that;
			return *this;
		}

		constexpr quantity operator*(NumericType that) const
		{
			return quantity(rawValue * that);
		}

		template<typename NT, typename N, typename D>
		constexpr auto operator*(quantity<NT, N, D> that) const
		{
			using combined_numerator   = detail::combine<numerator, N>;
			using combined_denominator = detail::combine<denominator, D>;

			using unsorted_numerator   = detail::remove_intersection<
				combined_numerator,
				combined_denominator>;

			using unsorted_denominator = detail::remove_intersection<
				combined_denominator,
				combined_numerator>;

			using result_numerator   = detail::sorted<unsorted_numerator>;
			using result_denominator = detail::sorted<unsorted_denominator>;

			using result_quantity = quantity<
				decltype(rawValue * that.rawValue),
				result_numerator,
				result_denominator>;

			return result_quantity(rawValue * that.rawValue);
		}

		constexpr quantity operator/(NumericType that) const
		{
			return quantity(rawValue / that);
		}

		template<typename NT, typename N, typename D>
		constexpr auto operator/(quantity<NT, N, D> that) const
		{
			// flip fraction rows around for division
			using combined_numerator   = detail::combine<numerator, D>;
			using combined_denominator = detail::combine<denominator, N>;

			using unsorted_numerator   = detail::remove_intersection<
				combined_numerator,
				combined_denominator>;

			using unsorted_denominator = detail::remove_intersection<
				combined_denominator,
				combined_numerator>;

			using result_numerator   = detail::sorted<unsorted_numerator>;
			using result_denominator = detail::sorted<unsorted_denominator>;

			using result_quantity = quantity<
				decltype(rawValue / that.rawValue),
				result_numerator,
				result_denominator>;

			return result_quantity(rawValue / that.rawValue);
		}

		template<intmax_t N, intmax_t D>
		constexpr quantity operator*(std::ratio<N, D>) const
		{
			return (*this) * N / D;
		}

		template<intmax_t N, intmax_t D>
		constexpr quantity operator/(std::ratio<N, D>) const
		{
			return (*this) / N * D;
		}

		template<typename N = Numerator, typename D = Denominator, typename
			= std::enable_if_t<N::size == 0 && D::size == 0>>
		constexpr operator NumericType()
		{
			return rawValue;
		}
	};

	template<typename MulType, typename NT, typename N, typename D, typename =
		typename std::enable_if<std::is_arithmetic<MulType>::value>::type>
	constexpr quantity<NT, N, D> operator*(MulType left, quantity<NT, N, D> right)
	{
		using unit_system = typename N::value_type;
		using unitless_quantity = quantity<NT,
			detail::sequence<unit_system>,
			detail::sequence<unit_system>>;
		return unitless_quantity(left) * right;
	}

	template<typename MulType, typename NT, typename N, typename D, typename =
		typename std::enable_if<std::is_arithmetic<MulType>::value>::type>
	constexpr quantity<NT, D, N> operator/(MulType left, quantity<NT, N, D> right)
	{
		using unit_system = typename N::value_type;
		using unitless_quantity = quantity<NT,
			detail::sequence<unit_system>,
			detail::sequence<unit_system>>;
		return unitless_quantity(left) / right;
	}

	template<intmax_t RN, intmax_t RD, typename QNT, typename QN, typename QD>
	constexpr quantity<QNT, QN, QD> operator*(
		std::ratio<RN, RD> left, quantity<QNT, QN, QD> right)
	{
		return right * left;
	}

	template<intmax_t RN, intmax_t RD, typename QNT, typename QN, typename QD>
	constexpr quantity<QNT, QD, QN> operator/(
		std::ratio<RN, RD> left, quantity<QNT, QN, QD> right)
	{
		return (1 / right) * left;
	}

	template<typename NumericType, typename UnitType, UnitType... U>
	using unit_base = quantity<NumericType,
		detail::sequence<UnitType, U...>,
		detail::sequence<UnitType>>;
}

#endif<|endoftext|>


<commit_before>/**************************************************************************/
/*!
    @file     Adafruit_MCP9808.cpp
    @author   K.Townsend (Adafruit Industries)
	@license  BSD (see license.txt)

	I2C Driver for Microchip's MCP9808 I2C Temp sensor

	This is a library for the Adafruit MCP9808 breakout
	----> http://www.adafruit.com/products/1782

	Adafruit invests time and resources providing this open source code,
	please support Adafruit and open-source hardware by purchasing
	products from Adafruit!

	@section  HISTORY

    v1.0 - First release
*/
/**************************************************************************/
#if ARDUINO >= 100
 #include "Arduino.h"
#else
 #include "WProgram.h"
#endif

#include <Wire.h>

#include "Adafruit_MCP9808.h"

/**************************************************************************/
/*!
    @brief  Instantiates a new MCP9808 class
*/
/**************************************************************************/
Adafruit_MCP9808::Adafruit_MCP9808() {
}

/**************************************************************************/
/*!
    @brief  Setups the HW
*/
/**************************************************************************/
boolean Adafruit_MCP9808::begin(uint8_t addr) {
  _i2caddr = addr;
  Wire.begin();

  if (read16(MCP9808_REG_MANUF_ID) != 0x0054) return false;
  if (read16(MCP9808_REG_DEVICE_ID) != 0x0400) return false;

  return true;
}

/**************************************************************************/
/*!
    @brief  Sets the output voltage to a fraction of source vref.  (Value
            can be 0..4095)

    @param[in]  output
                The 12-bit value representing the relationship between
                the DAC's input voltage and its output voltage.
    @param[in]  writeEEPROM
                If this value is true, 'output' will also be written
                to the MCP9808's internal non-volatile memory, meaning
                that the DAC will retain the current voltage output
                after power-down or reset.
*/
/**************************************************************************/
float Adafruit_MCP9808::readTempC( void )
{
  uint16_t t = read16(MCP9808_REG_AMBIENT_TEMP);

  float temp = t & 0x0FFF;
  if (t & 0x1000) temp *= -1;
  temp /=  16.0;

  return temp;
}

/**************************************************************************/
/*!
    @brief  Low level 16 bit read and write procedures!
*/
/**************************************************************************/

void Adafruit_MCP9808::write16(uint8_t reg, uint16_t value) {
    Wire.beginTransmission(_i2caddr);
    Wire.write((uint8_t)reg);
    Wire.write(value >> 8);
    Wire.write(value & 0xFF);
    Wire.endTransmission();
}

uint16_t Adafruit_MCP9808::read16(uint8_t reg) {
  uint16_t val;

  Wire.beginTransmission(_i2caddr);
  Wire.write((uint8_t)reg);
  Wire.endTransmission();

  Wire.requestFrom((uint8_t)_i2caddr, (uint8_t)2);
  val = Wire.read();
  val <<= 8;
  val |= Wire.read();
  return val;
}
<commit_msg>Update Adafruit_MCP9808.cpp<commit_after>/**************************************************************************/
/*!
    @file     Adafruit_MCP9808.cpp
    @author   K.Townsend (Adafruit Industries)
	@license  BSD (see license.txt)

	I2C Driver for Microchip's MCP9808 I2C Temp sensor

	This is a library for the Adafruit MCP9808 breakout
	----> http://www.adafruit.com/products/1782

	Adafruit invests time and resources providing this open source code,
	please support Adafruit and open-source hardware by purchasing
	products from Adafruit!

	@section  HISTORY

    v1.0 - First release
*/
/**************************************************************************/
#if ARDUINO >= 100
 #include "Arduino.h"
#else
 #include "WProgram.h"
#endif

#ifdef __AVR_ATtiny85__
 #include "TinyWireM.h"
 #define Wire TinyWireM
#else
 #include <Wire.h>
#endif

#include "Adafruit_MCP9808.h"

/**************************************************************************/
/*!
    @brief  Instantiates a new MCP9808 class
*/
/**************************************************************************/
Adafruit_MCP9808::Adafruit_MCP9808() {
}

/**************************************************************************/
/*!
    @brief  Setups the HW
*/
/**************************************************************************/
boolean Adafruit_MCP9808::begin(uint8_t addr) {
  _i2caddr = addr;
  Wire.begin();

  if (read16(MCP9808_REG_MANUF_ID) != 0x0054) return false;
  if (read16(MCP9808_REG_DEVICE_ID) != 0x0400) return false;

  return true;
}

/**************************************************************************/
/*!
    @brief  Sets the output voltage to a fraction of source vref.  (Value
            can be 0..4095)

    @param[in]  output
                The 12-bit value representing the relationship between
                the DAC's input voltage and its output voltage.
    @param[in]  writeEEPROM
                If this value is true, 'output' will also be written
                to the MCP9808's internal non-volatile memory, meaning
                that the DAC will retain the current voltage output
                after power-down or reset.
*/
/**************************************************************************/
float Adafruit_MCP9808::readTempC( void )
{
  uint16_t t = read16(MCP9808_REG_AMBIENT_TEMP);

  float temp = t & 0x0FFF;
  if (t & 0x1000) temp *= -1;
  temp /=  16.0;

  return temp;
}

/**************************************************************************/
/*!
    @brief  Low level 16 bit read and write procedures!
*/
/**************************************************************************/

void Adafruit_MCP9808::write16(uint8_t reg, uint16_t value) {
    Wire.beginTransmission(_i2caddr);
    Wire.write((uint8_t)reg);
    Wire.write(value >> 8);
    Wire.write(value & 0xFF);
    Wire.endTransmission();
}

uint16_t Adafruit_MCP9808::read16(uint8_t reg) {
  uint16_t val;

  Wire.beginTransmission(_i2caddr);
  Wire.write((uint8_t)reg);
  Wire.endTransmission();

  Wire.requestFrom((uint8_t)_i2caddr, (uint8_t)2);
  val = Wire.read();
  val <<= 8;
  val |= Wire.read();
  return val;
}
<|endoftext|>


<commit_before>// (C) Copyright 2009, Chong Wang, David Blei and Li Fei-Fei

// written by Chong Wang, chongw@cs.princeton.edu

// This file is part of slda.

// slda is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your
// option) any later version.

// slda 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 General Public License
// for more details.

// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA

#include <fstream>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <assert.h>
#include <stdio.h>
#include "corpus.h"

using std::pair;
using std::vector;
using std::string;
using std::cout;
using std::endl;
using std::cerr;

corpus::corpus()
{
    size_vocab = 0;
    num_classes = 0;
    num_total_words = 0;
}

corpus::~corpus()
{
    for (size_t i = 0; i < docs.size(); i ++)
        delete docs[i];
}

void corpus::read_data(const string & data_filename)
{
    std::ifstream infile(data_filename);
    string line;
    while(std::getline(infile, line))
    {
        std::stringstream stream(line);
        document* doc = new document();

        stream >> doc->label;
        if(doc->label >= num_classes)
            num_classes = doc->label + 1;

        // stream now contains "word_id:count" strings
        string token;
        while(stream >> token)
        {
            pair<int, int> vals = get_word_data(token);
            int word = vals.first;
            int count = vals.second;
            doc->words.push_back(word);
            doc->counts.push_back(count);
            doc->total += count;

            if(word >= size_vocab)
                size_vocab = word + 1;
        }

        num_total_words += doc->words.size();
        docs.push_back(doc);
    }

    infile.close();

    cout << docs.size() << " documents, "
         << size_vocab << " terms, "
         << num_total_words << " total words, "
         << num_classes << " classes" << endl;
}

pair<int, int> corpus::get_word_data(const string & str) const
{
    size_t idx = str.find_first_of(':');
    std::istringstream wordstr(str.substr(0, idx));
    std::istringstream countstr(str.substr(idx + 1));

    int word = 0;
    int count = 0;
    wordstr >> word;
    countstr >> count;

    return std::make_pair(word, count);
}

int corpus::max_corpus_length() {
    size_t max_length = 0;
    for (size_t d = 0; d < docs.size(); d++) {
        if (docs[d]->words.size() > max_length)
            max_length = docs[d]->words.size();
    }
    return max_length;
}
<commit_msg>(minor) have slda print to stderr instead of stdout<commit_after>// (C) Copyright 2009, Chong Wang, David Blei and Li Fei-Fei

// written by Chong Wang, chongw@cs.princeton.edu

// This file is part of slda.

// slda is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your
// option) any later version.

// slda 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 General Public License
// for more details.

// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA

#include <fstream>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <assert.h>
#include <stdio.h>
#include "corpus.h"

using std::pair;
using std::vector;
using std::string;
using std::cout;
using std::endl;
using std::cerr;

corpus::corpus()
{
    size_vocab = 0;
    num_classes = 0;
    num_total_words = 0;
}

corpus::~corpus()
{
    for (size_t i = 0; i < docs.size(); i ++)
        delete docs[i];
}

void corpus::read_data(const string & data_filename)
{
    std::ifstream infile(data_filename);
    string line;
    while(std::getline(infile, line))
    {
        std::stringstream stream(line);
        document* doc = new document();

        stream >> doc->label;

        if(doc->label >= num_classes)
            num_classes = doc->label + 1;

        // stream now contains "word_id:count" strings
        string token;
        while(stream >> token)
        {
            pair<int, int> vals = get_word_data(token);
            int word = vals.first;
            int count = vals.second;
            doc->words.push_back(word);
            doc->counts.push_back(count);
            doc->total += count;

            if(word >= size_vocab)
                size_vocab = word + 1;
        }

        num_total_words += doc->words.size();
        docs.push_back(doc);
    }

    infile.close();

    cerr << docs.size() << " documents, "
         << size_vocab << " terms, "
         << num_total_words << " total words, "
         << num_classes << " classes" << endl;
}

pair<int, int> corpus::get_word_data(const string & str) const
{
    size_t idx = str.find_first_of(':');
    std::istringstream wordstr(str.substr(0, idx));
    std::istringstream countstr(str.substr(idx + 1));

    int word = 0;
    int count = 0;
    wordstr >> word;
    countstr >> count;

    return std::make_pair(word, count);
}

int corpus::max_corpus_length() {
    size_t max_length = 0;
    for (size_t d = 0; d < docs.size(); d++) {
        if (docs[d]->words.size() > max_length)
            max_length = docs[d]->words.size();
    }
    return max_length;
}
<|endoftext|>


<commit_before>#include <iomanip>
#include "InteractiveInterpreter.h"
#include "InterpretedDefinition.h"
#include "Util.h"
#include "Globals.h"

InteractiveInterpreter::InteractiveInterpreter(Emmental& interpreter)
	: Interpreter(interpreter)
{
	GenerateCommands();
}

int InteractiveInterpreter::RunLoop()
{
	Interpreter.OutputStream << "Entering Interactive Mode" << std::endl;
	Interpreter.OutputStream << "Inputs not starting with '__' will be interpreted by Emmental." << std::endl;
	Interpreter.OutputStream << "Type __help for a list of commands, or __exit to exit." << std::endl;

	while (true)
	{
		Interpreter.OutputStream << std::endl;
		Interpreter.OutputStream << "> ";
		std::string input;
		std::getline(Interpreter.InputStream, input);
		Interpreter.OutputStream << std::endl;

		if (EnableCommands)
		{
			// Special command to exit the loop
			if (input.find("__exit") == 0)
				return EXIT_SUCCESS;

			if (ParseCommand(input))
				continue;
		}

		for (auto&& x : input)
		{
			SymbolT symbol = (SymbolT)x;
			Interpreter.Interpret(symbol);
		}

		if (Globals::DebugMode)
		{
			Util::DescribeMemory(Interpreter, Interpreter.OutputStream);
		}
	}
}

void InteractiveInterpreter::AddCommand(const InteractiveCommand& command) { Commands.push_back(command); }

void InteractiveInterpreter::GenerateCommands()
{
	// These commands are handled as special cases, they'll never be called normally.
	AddCommand(InteractiveCommand("exit", "Exits this program.", nullptr));
	AddCommand(InteractiveCommand("help", "Shows this list.", nullptr));

	// Normal commands here
	AddCommand(InteractiveCommand("disablecommands", "Disables all commands, interpreting all input as Emmental code.", [&](Emmental& interpreter, std::string)
	{
		Util::Colorize(Util::ConsoleColor::BrightYellow, interpreter.OutputStream);
		interpreter.OutputStream << "WARNING! ";
		Util::Colorize(Util::ConsoleColor::Default, interpreter.OutputStream);
		interpreter.OutputStream << "All commands will be disabled, including __exit. Do you want to continue? (Y/N)";

		std::string answer;
		std::getline(Interpreter.InputStream, answer);
		if (answer == "y" || answer == "Y")
		{
			EnableCommands = false;
			interpreter.OutputStream << "All commands disabled." << std::endl;
		}
		else
		{
			interpreter.OutputStream << "Operation cancelled. " << std::endl;
		}
	}));
	AddCommand(InteractiveCommand("reset", "Resets the interpreter back to its original state.", [](Emmental& interpreter, std::string)
	{
		interpreter.Reset();
		interpreter.OutputStream << "Interpreter reset." << std::endl;
	}));

	AddCommand(InteractiveCommand("clearstack", "Clears the stack.", [](Emmental& interpreter, std::string)
	{
		interpreter.ClearStack();
		interpreter.OutputStream << "Stack cleared." << std::endl;
	}));

	AddCommand(InteractiveCommand("clearqueue", "Clears the queue.", [](Emmental& interpreter, std::string)
	{
		interpreter.ClearQueue();
		interpreter.OutputStream << "Queue cleared." << std::endl;
	}));

	AddCommand(InteractiveCommand("resetdefs", "Resets all symbol definitions back to their original native definitions.", [](Emmental& interpreter, std::string)
	{
		interpreter.ResetDefinitions();
		interpreter.OutputStream << "Symbol definitions reset to original native definitions." << std::endl;
	}));

	AddCommand(InteractiveCommand("undef", "Undefines a symbol. Pass the symbol number as an argument.", [](Emmental& interpreter, std::string arg)
	{
		SymbolT symbol;

		try
		{
			symbol = std::stoi(arg);
		}
		catch (std::invalid_argument)
		{
			interpreter.OutputStream << "Invalid symbol number." << std::endl;
			return;
		}
		catch (std::out_of_range)
		{
			interpreter.OutputStream << "Symbol value out of range." << std::endl;
			return;
		}

		interpreter.Undefine(symbol);
		interpreter.OutputStream << "Undefined symbol ";
		Util::DescribeSymbol(symbol, interpreter.OutputStream);
		interpreter.OutputStream << "." << std::endl;

	}));

	AddCommand(InteractiveCommand("debug", "Toggles debug mode on/off", [](Emmental& interpreter, std::string)
	{
		Globals::DebugMode = !Globals::DebugMode;
		interpreter.OutputStream << "Debug mode is now " << (Globals::DebugMode ? "on" : "off") << "." << std::endl;
	}));

	AddCommand(InteractiveCommand("color", "Toggles Virtual Console coloring on/off", [](Emmental& interpreter, std::string)
	{
		Globals::UseVirtualConsole = !Globals::UseVirtualConsole;
		interpreter.OutputStream << "Virtual Console coloring is now " << (Globals::UseVirtualConsole ? "on" : "off") << "." << std::endl;
	}));

	AddCommand(InteractiveCommand("optimize", "Toggles program optimization on/off", [](Emmental& interpreter, std::string)
	{
		Globals::OptimizeProgram = !Globals::OptimizeProgram;
		interpreter.OutputStream << "Optimization is now " << (Globals::OptimizeProgram ? "on" : "off") << "." << std::endl;
	}));

	AddCommand(InteractiveCommand("memory", "Shows the current stack and queue", [](Emmental& interpreter, std::string)
	{
		Util::DescribeMemory(interpreter, interpreter.OutputStream);
		interpreter.OutputStream << std::endl;
	}));

	AddCommand(InteractiveCommand("pushraw",
		"Pushes its argument into the stack (interpreted as raw ASCII bytes).",
		[](Emmental& interpreter, std::string args)
	{
		for (auto& symbol : args)
		{
			interpreter.Push(symbol);
			Util::DescribeSymbol(symbol, interpreter.OutputStream);
			interpreter.OutputStream << ", ";
		}

		interpreter.OutputStream << std::endl;
		interpreter.OutputStream << "Pushed " << args.length() << " bytes into the stack." << std::endl;
		interpreter.OutputStream << std::endl;

		Util::DescribeMemory(interpreter, interpreter.OutputStream);
		interpreter.OutputStream << std::endl;

	}));

	AddCommand(InteractiveCommand("defs",
		"Without argument: Displays all current symbol definitions. With symbol number as argument: Displays all captured definitions for the symbol.",
		[](Emmental& interpreter, std::string arg)
	{
		if (arg.empty())
		{
			interpreter.OutputStream << "Current interpreter definitions: " << std::endl;
			Util::DescribeDefinitions(interpreter.CopyDefinitions(), interpreter.OutputStream);
			interpreter.OutputStream << std::endl;
		}
		else
		{
			SymbolT symbol;

			try
			{
				symbol = std::stoi(arg);
			}
			catch (std::invalid_argument)
			{
				interpreter.OutputStream << "Invalid symbol number." << std::endl;
				return;
			}
			catch (std::out_of_range)
			{
				interpreter.OutputStream << "Symbol value out of range." << std::endl;
				return;
			}

			Util::DescribeDefinition(symbol, interpreter.CopyDefinitions(), true, interpreter.OutputStream);
			interpreter.OutputStream << std::endl;
		}
	}));

	AddCommand(InteractiveCommand("info", "Display interpreter information.", [](Emmental& interpreter, std::string)
	{
		interpreter.OutputStream << "Gory Emmental Interpreter 1.0.0 by Davipb" << std::endl;

		Util::Colorize(Util::ConsoleColor::BrightGreen, interpreter.OutputStream);
		interpreter.OutputStream << "== Compile-Time Settings ==" << std::endl;
		Util::Colorize(Util::ConsoleColor::Default, interpreter.OutputStream);
		interpreter.OutputStream << "Symbol Type: " << typeid(SymbolT).name() << std::endl;
		interpreter.OutputStream << "Symbol Size: " << sizeof(SymbolT) << " byte(s)" << std::endl;
		interpreter.OutputStream << "Max Stack Size: " << EMMENTAL_MAX_STACK_SIZE << std::endl;
		interpreter.OutputStream << "Max Queue Size: " << EMMENTAL_MAX_QUEUE_SIZE << std::endl;
		interpreter.OutputStream << "Max Recursion Level: " << EMMENTAL_MAX_RECURSION_LEVEL << std::endl;

		Util::Colorize(Util::ConsoleColor::BrightGreen, interpreter.OutputStream);
		interpreter.OutputStream << "== Runtime Settings ==" << std::endl;
		Util::Colorize(Util::ConsoleColor::Default, interpreter.OutputStream);
		interpreter.OutputStream << "Debug Mode: " << (Globals::DebugMode ? "On" : "Off") << std::endl;
		interpreter.OutputStream << "Colors: " << (Globals::UseVirtualConsole ? "On" : "Off") << std::endl;
		interpreter.OutputStream << "Optimization: " << (Globals::OptimizeProgram ? "On" : "Off") << std::endl;

	}));
}

bool InteractiveInterpreter::ParseCommand(std::string input)
{
	if (input.find("__") != 0)
		return false;

	std::string command = input.substr(2, input.size() - 2);

	if (command.find("help") == 0)
	{
		Interpreter.OutputStream << "Commands are case-sensitive. Arguments come right after a command." << std::endl;
		Interpreter.OutputStream << std::endl;

		for (auto& x : Commands)
		{
			Util::Colorize(Util::ConsoleColor::BrightGreen, Interpreter.OutputStream);
			Interpreter.OutputStream << "__" << x.GetName() << ": ";
			Util::Colorize(Util::ConsoleColor::Default, Interpreter.OutputStream);
			Interpreter.OutputStream << x.GetDescription() << std::endl;
		}
		return true;
	}

	std::string commandName = command;
	std::string argument;
	auto spaceLocation = commandName.find(' ');
	if (spaceLocation != commandName.length())
	{
		commandName = command.substr(0, spaceLocation);
		argument = command.substr(spaceLocation + 1, command.length() - spaceLocation - 1);
	}

	for (auto& x : Commands)
	{
		if (x.GetName() == commandName)
		{
			x.Execute(Interpreter, argument);
			return true;
		}
	}

	Util::Colorize(Util::ConsoleColor::Red, Interpreter.OutputStream);
	Interpreter.OutputStream << "Unknown command '" << commandName << "'. Use __help for a list of commands." << std::endl;
	Util::Colorize(Util::ConsoleColor::Default, Interpreter.OutputStream);

	return true;
}<commit_msg>Fix command parsing & improve error reporting<commit_after>#include <iomanip>
#include "InteractiveInterpreter.h"
#include "InterpretedDefinition.h"
#include "Util.h"
#include "Globals.h"

InteractiveInterpreter::InteractiveInterpreter(Emmental& interpreter)
	: Interpreter(interpreter)
{
	GenerateCommands();
}

int InteractiveInterpreter::RunLoop()
{
	Interpreter.OutputStream << "Entering Interactive Mode" << std::endl;
	Interpreter.OutputStream << "Inputs not starting with '__' will be interpreted by Emmental." << std::endl;
	Interpreter.OutputStream << "Type __help for a list of commands, or __exit to exit." << std::endl;

	while (true)
	{
		Interpreter.OutputStream << std::endl;
		Interpreter.OutputStream << "> ";
		std::string input;
		std::getline(Interpreter.InputStream, input);
		Interpreter.OutputStream << std::endl;

		if (EnableCommands)
		{
			// Special command to exit the loop
			if (input.find("__exit") == 0)
				return EXIT_SUCCESS;

			if (ParseCommand(input))
				continue;
		}

		for (auto&& x : input)
		{
			SymbolT symbol = (SymbolT)x;
			Interpreter.Interpret(symbol);
		}

		if (Globals::DebugMode)
		{
			Util::DescribeMemory(Interpreter, Interpreter.OutputStream);
		}
	}
}

void InteractiveInterpreter::AddCommand(const InteractiveCommand& command) { Commands.push_back(command); }

void InteractiveInterpreter::GenerateCommands()
{
	// These commands are handled as special cases, they'll never be called normally.
	AddCommand(InteractiveCommand("exit", "Exits this program.", nullptr));
	AddCommand(InteractiveCommand("help", "Shows this list.", nullptr));

	// Normal commands here
	AddCommand(InteractiveCommand("disablecommands", "Disables all commands, interpreting all input as Emmental code.", [&](Emmental& interpreter, std::string)
	{
		Util::Colorize(Util::ConsoleColor::BrightYellow, interpreter.OutputStream);
		interpreter.OutputStream << "WARNING! ";
		Util::Colorize(Util::ConsoleColor::Default, interpreter.OutputStream);
		interpreter.OutputStream << "All commands will be disabled, including __exit. Do you want to continue? (Y/N)";

		std::string answer;
		std::getline(Interpreter.InputStream, answer);
		if (answer == "y" || answer == "Y")
		{
			EnableCommands = false;
			interpreter.OutputStream << "All commands disabled." << std::endl;
		}
		else
		{
			interpreter.OutputStream << "Operation cancelled. " << std::endl;
		}
	}));
	AddCommand(InteractiveCommand("reset", "Resets the interpreter back to its original state.", [](Emmental& interpreter, std::string)
	{
		interpreter.Reset();
		interpreter.OutputStream << "Interpreter reset." << std::endl;
	}));

	AddCommand(InteractiveCommand("clearstack", "Clears the stack.", [](Emmental& interpreter, std::string)
	{
		interpreter.ClearStack();
		interpreter.OutputStream << "Stack cleared." << std::endl;
	}));

	AddCommand(InteractiveCommand("clearqueue", "Clears the queue.", [](Emmental& interpreter, std::string)
	{
		interpreter.ClearQueue();
		interpreter.OutputStream << "Queue cleared." << std::endl;
	}));

	AddCommand(InteractiveCommand("resetdefs", "Resets all symbol definitions back to their original native definitions.", [](Emmental& interpreter, std::string)
	{
		interpreter.ResetDefinitions();
		interpreter.OutputStream << "Symbol definitions reset to original native definitions." << std::endl;
	}));

	AddCommand(InteractiveCommand("undef", "Undefines a symbol. Pass the symbol number as an argument.", [](Emmental& interpreter, std::string arg)
	{
		SymbolT symbol;

		try
		{
			symbol = std::stoi(arg);
		}
		catch (std::invalid_argument)
		{
			Util::Colorize(Util::ConsoleColor::Red, interpreter.OutputStream);
			interpreter.OutputStream << "Invalid symbol number." << std::endl;
			Util::Colorize(Util::ConsoleColor::Default, interpreter.OutputStream);
			return;
		}
		catch (std::out_of_range)
		{
			Util::Colorize(Util::ConsoleColor::Red, interpreter.OutputStream);
			interpreter.OutputStream << "Symbol value out of range." << std::endl;
			Util::Colorize(Util::ConsoleColor::Default, interpreter.OutputStream);
			return;
		}

		interpreter.Undefine(symbol);
		interpreter.OutputStream << "Undefined symbol ";
		Util::DescribeSymbol(symbol, interpreter.OutputStream);
		interpreter.OutputStream << "." << std::endl;

	}));

	AddCommand(InteractiveCommand("debug", "Toggles debug mode on/off", [](Emmental& interpreter, std::string)
	{
		Globals::DebugMode = !Globals::DebugMode;
		interpreter.OutputStream << "Debug mode is now " << (Globals::DebugMode ? "on" : "off") << "." << std::endl;
	}));

	AddCommand(InteractiveCommand("color", "Toggles Virtual Console coloring on/off", [](Emmental& interpreter, std::string)
	{
		Globals::UseVirtualConsole = !Globals::UseVirtualConsole;
		interpreter.OutputStream << "Virtual Console coloring is now " << (Globals::UseVirtualConsole ? "on" : "off") << "." << std::endl;
	}));

	AddCommand(InteractiveCommand("optimize", "Toggles program optimization on/off", [](Emmental& interpreter, std::string)
	{
		Globals::OptimizeProgram = !Globals::OptimizeProgram;
		interpreter.OutputStream << "Optimization is now " << (Globals::OptimizeProgram ? "on" : "off") << "." << std::endl;
	}));

	AddCommand(InteractiveCommand("memory", "Shows the current stack and queue", [](Emmental& interpreter, std::string)
	{
		Util::DescribeMemory(interpreter, interpreter.OutputStream);
		interpreter.OutputStream << std::endl;
	}));

	AddCommand(InteractiveCommand("pushraw",
		"Pushes its argument into the stack (interpreted as raw ASCII bytes).",
		[](Emmental& interpreter, std::string args)
	{
		for (auto& symbol : args)
		{
			interpreter.Push(symbol);
			Util::DescribeSymbol(symbol, interpreter.OutputStream);
			interpreter.OutputStream << ", ";
		}

		interpreter.OutputStream << std::endl;
		interpreter.OutputStream << "Pushed " << args.length() << " bytes into the stack." << std::endl;
		interpreter.OutputStream << std::endl;

		Util::DescribeMemory(interpreter, interpreter.OutputStream);
		interpreter.OutputStream << std::endl;

	}));

	AddCommand(InteractiveCommand("defs",
		"Without argument: Displays all current symbol definitions. With symbol number as argument: Displays all captured definitions for the symbol.",
		[](Emmental& interpreter, std::string arg)
	{
		if (arg.empty())
		{
			interpreter.OutputStream << "Current interpreter definitions: " << std::endl;
			Util::DescribeDefinitions(interpreter.CopyDefinitions(), interpreter.OutputStream);
			interpreter.OutputStream << std::endl;
		}
		else
		{
			SymbolT symbol;

			try
			{
				symbol = std::stoi(arg);
			}
			catch (std::invalid_argument)
			{
				Util::Colorize(Util::ConsoleColor::Red, interpreter.OutputStream);
				interpreter.OutputStream << "Invalid symbol number." << std::endl;
				Util::Colorize(Util::ConsoleColor::Default, interpreter.OutputStream);
				return;
			}
			catch (std::out_of_range)
			{
				Util::Colorize(Util::ConsoleColor::Red, interpreter.OutputStream);
				interpreter.OutputStream << "Symbol value out of range." << std::endl;
				Util::Colorize(Util::ConsoleColor::Default, interpreter.OutputStream);
				return;
			}

			Util::DescribeDefinition(symbol, interpreter.CopyDefinitions(), true, interpreter.OutputStream);
			interpreter.OutputStream << std::endl;
		}
	}));

	AddCommand(InteractiveCommand("info", "Display interpreter information.", [](Emmental& interpreter, std::string)
	{
		interpreter.OutputStream << "Gory Emmental Interpreter 1.0.0 by Davipb" << std::endl;

		Util::Colorize(Util::ConsoleColor::BrightGreen, interpreter.OutputStream);
		interpreter.OutputStream << "== Compile-Time Settings ==" << std::endl;
		Util::Colorize(Util::ConsoleColor::Default, interpreter.OutputStream);
		interpreter.OutputStream << "Symbol Type: " << typeid(SymbolT).name() << std::endl;
		interpreter.OutputStream << "Symbol Size: " << sizeof(SymbolT) << " byte(s)" << std::endl;
		interpreter.OutputStream << "Max Stack Size: " << EMMENTAL_MAX_STACK_SIZE << std::endl;
		interpreter.OutputStream << "Max Queue Size: " << EMMENTAL_MAX_QUEUE_SIZE << std::endl;
		interpreter.OutputStream << "Max Recursion Level: " << EMMENTAL_MAX_RECURSION_LEVEL << std::endl;

		Util::Colorize(Util::ConsoleColor::BrightGreen, interpreter.OutputStream);
		interpreter.OutputStream << "== Runtime Settings ==" << std::endl;
		Util::Colorize(Util::ConsoleColor::Default, interpreter.OutputStream);
		interpreter.OutputStream << "Debug Mode: " << (Globals::DebugMode ? "On" : "Off") << std::endl;
		interpreter.OutputStream << "Colors: " << (Globals::UseVirtualConsole ? "On" : "Off") << std::endl;
		interpreter.OutputStream << "Optimization: " << (Globals::OptimizeProgram ? "On" : "Off") << std::endl;

	}));
}

bool InteractiveInterpreter::ParseCommand(std::string input)
{
	if (input.find("__") != 0)
		return false;

	std::string command = input.substr(2, input.size() - 2);

	if (command.find("help") == 0)
	{
		Interpreter.OutputStream << "Commands are case-sensitive. Arguments come right after a command." << std::endl;
		Interpreter.OutputStream << std::endl;

		for (auto& x : Commands)
		{
			Util::Colorize(Util::ConsoleColor::BrightGreen, Interpreter.OutputStream);
			Interpreter.OutputStream << "__" << x.GetName() << ": ";
			Util::Colorize(Util::ConsoleColor::Default, Interpreter.OutputStream);
			Interpreter.OutputStream << x.GetDescription() << std::endl;
		}
		return true;
	}

	std::string commandName = command;
	std::string argument;
	auto spaceLocation = commandName.find(' ');
	if (spaceLocation < command.length())
	{
		commandName = command.substr(0, spaceLocation);
		argument = command.substr(spaceLocation + 1, command.length() - spaceLocation - 1);
	}

	for (auto& x : Commands)
	{
		if (x.GetName() == commandName)
		{
			x.Execute(Interpreter, argument);
			return true;
		}
	}

	Util::Colorize(Util::ConsoleColor::Red, Interpreter.OutputStream);
	Interpreter.OutputStream << "Unknown command '" << commandName << "'. Use __help for a list of commands." << std::endl;
	Util::Colorize(Util::ConsoleColor::Default, Interpreter.OutputStream);

	return true;
}<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkProcrustesAlignmentFilter.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkProcrustesAlignmentFilter.h"
#include "vtkObjectFactory.h"
#include "vtkLandmarkTransform.h"
#include "vtkTransformPolyDataFilter.h"
#include "vtkPolyData.h"
#include "vtkMath.h"

vtkCxxRevisionMacro(vtkProcrustesAlignmentFilter, "1.15");
vtkStandardNewMacro(vtkProcrustesAlignmentFilter);

//----------------------------------------------------------------------------
// protected
vtkProcrustesAlignmentFilter::vtkProcrustesAlignmentFilter()
{
  this->LandmarkTransform = vtkLandmarkTransform::New();

  this->MeanPoints = vtkPoints::New();
}

//----------------------------------------------------------------------------
// protected
vtkProcrustesAlignmentFilter::~vtkProcrustesAlignmentFilter()
{
  if(this->LandmarkTransform)
    {
    this->LandmarkTransform->Delete();
    }
  if(this->MeanPoints)
    {
    this->MeanPoints->Delete();
    }
}

//----------------------------------------------------------------------------
// Calculate the centroid of a point cloud
static inline void Centroid(vtkPoints* pd, double *cp)
{
  // Center point
  cp[0] = 0; cp[1] = 0; cp[2] = 0;

  int np = pd->GetNumberOfPoints();

  // Calculate center of shape
  for (int i = 0; i < np; i++)
    {
    double p[3];
    pd->GetPoint(i, p);
    cp[0] += p[0]; cp[1] += p[1]; cp[2] += p[2];
    }
  cp[0] /= np; cp[1] /= np; cp[2] /= np;
}

//----------------------------------------------------------------------------
// Calculate the centroid size of a point cloud
static inline double CentroidSize(vtkPoints* pd, double *cp)
{
  Centroid(pd, cp);

  double S = 0;
  for (int i = 0; i < pd->GetNumberOfPoints(); i++)
    {
    double p[3];
    pd->GetPoint(i, p);
    S += vtkMath::Distance2BetweenPoints(p,cp);
  }

  return sqrt(S);
}

//----------------------------------------------------------------------------
// Translation of point cloud. Could be done using transformations
static inline void TranslateShape(vtkPoints* pd, double *tp)
{
  for (int i = 0; i < pd->GetNumberOfPoints(); i++)
    {
    double p[3];
    pd->GetPoint(i, p);
    pd->SetPoint(i, p[0]+tp[0], p[1]+tp[1], p[2]+tp[2]);
    }
}

//----------------------------------------------------------------------------
// Scaling of point cloud. Could be done using transformations
static inline void ScaleShape(vtkPoints* pd, double S)
{
  for (int i = 0; i < pd->GetNumberOfPoints(); i++)
    {
    double p[3];
    pd->GetPoint(i, p);
    pd->SetPoint(i, p[0]*S, p[1]*S, p[2]*S);
    }
}

//----------------------------------------------------------------------------
// Normalise a point cloud to have centroid (0,0,0) and centroid size 1
static inline int NormaliseShape(vtkPoints* pd)
{
  double cp[3];
  double S = CentroidSize(pd, cp);
  if (S == 0)
    return 0;

  double tp[3];
  tp[0] = -cp[0]; tp[1] = -cp[1]; tp[2] = -cp[2];
  TranslateShape(pd, tp);
  ScaleShape(pd, 1/S);
  return 1;
}

//----------------------------------------------------------------------------
// protected
void vtkProcrustesAlignmentFilter::Execute()
{
  vtkDebugMacro(<<"Execute()");

  if(!this->vtkProcessObject::Inputs)
    {
    vtkErrorMacro(<<"No input!");
    return;
    }

  int i,v;

  const int N_SETS = this->vtkProcessObject::GetNumberOfInputs();

  // copy the inputs across
  // (really actually only the points need to be deep copied since the rest stays the same)
  for(i=0;i<N_SETS;i++)
    {
    this->GetOutput(i)->DeepCopy(this->GetInput(i));
    }

  // the number of points is determined by the first input (they must all be the same)
  const int N_POINTS = this->GetInput(0)->GetNumberOfPoints();

  vtkDebugMacro(<<"N_POINTS is " <<N_POINTS);

  if(N_POINTS == 0)
    {
    vtkErrorMacro(<<"No points!");
    return;
    }

  // all the inputs must have the same number of points to consider executing
  for(i=1;i<N_SETS;i++)
    {
    if(this->GetInput(i)->GetNumberOfPoints() != N_POINTS)
      {
      vtkErrorMacro(<<"The inputs have different numbers of points!");
      return;
      }
    }

//  vtkPoints *mean_points = vtkPoints::New();
  MeanPoints->DeepCopy(this->GetInput(0)->GetPoints());
  // our initial estimate of the mean comes from the first example in the set

  // we keep a record of the first mean to fix the orientation and scale
  // (which are otherwise undefined and the loop will not converge)
  vtkPoints *first_mean = vtkPoints::New();
  first_mean->DeepCopy(MeanPoints);

  // If the similarity transform is used, the mean shape must be normalised
  // to avoid shrinking
  if (this->LandmarkTransform->GetMode() == VTK_LANDMARK_SIMILARITY)
  {
    if (!NormaliseShape(MeanPoints)) {
      vtkErrorMacro(<<"Centroid size zero");
      return;
    }
    if (!NormaliseShape(first_mean)) {
      vtkErrorMacro(<<"Centroid size zero");
      return;
    }
  }

  // storage for the new mean that is being calculated
  vtkPoints *new_mean = vtkPoints::New();
  new_mean->SetNumberOfPoints(N_POINTS);

  // compute mean and align all the shapes to it, until convergence
  int converged=0; // bool converged=false
  int iterations=0;
  const int MAX_ITERATIONS=5;
  double difference;
  double point[3],p[3],p2[3];
  double outPoint[3];
  do { // (while not converged)

    // align each pointset with the mean
    for(i=0;i<N_SETS;i++)
      {
      this->LandmarkTransform->SetSourceLandmarks(this->GetOutput(i)->GetPoints());
      this->LandmarkTransform->SetTargetLandmarks(MeanPoints);
      this->LandmarkTransform->Update();
      for(v=0;v<N_POINTS;v++)
        {
        this->LandmarkTransform->InternalTransformPoint(
          this->GetOutput(i)->GetPoint(v), outPoint);
        this->GetOutput(i)->GetPoints()->SetPoint(v, outPoint);
        }
      }

    // compute the new mean (just average the point locations)
    for(v=0;v<N_POINTS;v++)
      {
      point[0]=0.0F;
      point[1]=0.0F;
      point[2]=0.0F;
      for(i=0;i<N_SETS;i++)
        {
        this->GetOutput(i)->GetPoint(v, p);
        point[0]+=p[0];
        point[1]+=p[1];
        point[2]+=p[2];
        }
      p[0] = point[0]/(double)N_SETS;
      p[1] = point[1]/(double)N_SETS;
      p[2] = point[2]/(double)N_SETS;
      new_mean->SetPoint(v, p);
      }

    // align the new mean with the fixed mean if the transform
    // is similarity or rigidbody. It is not yet decided what to do with affine
    if (this->LandmarkTransform->GetMode() == VTK_LANDMARK_SIMILARITY ||
        this->LandmarkTransform->GetMode() == VTK_LANDMARK_RIGIDBODY){
      this->LandmarkTransform->SetSourceLandmarks(new_mean);
      this->LandmarkTransform->SetTargetLandmarks(first_mean);
      this->LandmarkTransform->Update();
      for(v=0;v<N_POINTS;v++)
        {
        this->LandmarkTransform->InternalTransformPoint(
          new_mean->GetPoint(v), outPoint);
        new_mean->SetPoint(v, outPoint);
        }
    }

    // If the similarity transform is used, the mean shape must be normalised
    // to avoid shrinking
    if (this->LandmarkTransform->GetMode() == VTK_LANDMARK_SIMILARITY) {
      if (!NormaliseShape(new_mean)) {
        vtkErrorMacro(<<"Centroid size zero");
        return;
      }
    }

    // the new mean becomes our mean
    // compute the difference between the two
    difference = 0.0F;
    for(v=0;v<N_POINTS;v++)
      {
        new_mean->GetPoint(v, p);
        MeanPoints->GetPoint(v, p2);
        difference += vtkMath::Distance2BetweenPoints(p,p2);
        p2[0] = p[0];
        p2[1] = p[1];
        p2[2] = p[2];
      }

    // test for convergence
    iterations++;
    vtkDebugMacro( << "Difference after " << iterations << " iteration(s) is: " << difference);
    if(difference<1e-6 || iterations>=MAX_ITERATIONS) {
      converged=1; // true
      }

    // The convergence test is that the sum of the distances between the
    // points on mean(t) and mean(t-1) is less than a very small number.
    // Procrustes shouldn't need more than 2 or 3 iterations but things could go wrong
    // so we impose an iteration limit to avoid getting stuck in an infinite loop.

  } while(!converged);

  if(iterations>=MAX_ITERATIONS) {
    vtkDebugMacro( << "Procrustes did not converge in  " << MAX_ITERATIONS << " iterations! Objects may not be aligned. Difference = " <<
      difference);
    // we don't throw an Error here since the shapes most probably *are* aligned, but the
    // numerical precision is worse than our convergence test anticipated.
    }
  else {
    vtkDebugMacro( << "Procrustes required " << iterations << " iterations to converge to " <<
      difference);
    }

  // clean up
  first_mean->Delete();
  new_mean->Delete();
}

//----------------------------------------------------------------------------
// public
void vtkProcrustesAlignmentFilter::SetNumberOfInputs(int n)
{
  this->vtkProcessObject::SetNumberOfInputs(n);
  this->vtkSource::SetNumberOfOutputs(n);

  // initialise the outputs
  for(int i=0;i<n;i++)
    {
    vtkPoints *points = vtkPoints::New();
    vtkPolyData *ps = vtkPolyData::New();
    ps->SetPoints(points);
    points->Delete();
    this->vtkSource::SetNthOutput(i,ps);
    ps->Delete();
    }

  // is this the right thing to be doing here? if we don't initialise the outputs here
  // then the filter crashes but vtkPolyData may not be the type of the inputs
}

//----------------------------------------------------------------------------
// public
void vtkProcrustesAlignmentFilter::SetInput(int idx,vtkPointSet* p)
{
  if(idx<0 || idx>=this->vtkProcessObject::GetNumberOfInputs())
    {
    vtkErrorMacro(<<"Index out of bounds in SetInput!");
    return;
    }

  this->vtkProcessObject::SetNthInput(idx,p);
}

//----------------------------------------------------------------------------
// public
vtkPointSet* vtkProcrustesAlignmentFilter::GetInput(int idx)
{
  if(idx<0 || idx>=this->vtkProcessObject::GetNumberOfInputs())
    {
    vtkErrorMacro(<<"Index out of bounds in GetInput!");
    return NULL;
    }

  return static_cast<vtkPointSet*>(this->vtkProcessObject::Inputs[idx]);
}

//----------------------------------------------------------------------------
// public
vtkPointSet* vtkProcrustesAlignmentFilter::GetOutput(int idx)
{
  if(idx<0 || idx>=this->vtkSource::GetNumberOfOutputs())
    {
    vtkErrorMacro(<<"Index out of bounds in GetOutput!");
    return NULL;
    }

  return static_cast<vtkPointSet*>(this->vtkSource::GetOutput(idx));
}

//----------------------------------------------------------------------------
// public
void vtkProcrustesAlignmentFilter::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);
  this->LandmarkTransform->PrintSelf(os,indent);
  this->MeanPoints->PrintSelf(os, indent);
}

<commit_msg>BUG#773: Fix for code that was assuming GetPoint returned a pointer into the array.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkProcrustesAlignmentFilter.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkProcrustesAlignmentFilter.h"
#include "vtkObjectFactory.h"
#include "vtkLandmarkTransform.h"
#include "vtkTransformPolyDataFilter.h"
#include "vtkPolyData.h"
#include "vtkMath.h"

vtkCxxRevisionMacro(vtkProcrustesAlignmentFilter, "1.16");
vtkStandardNewMacro(vtkProcrustesAlignmentFilter);

//----------------------------------------------------------------------------
// protected
vtkProcrustesAlignmentFilter::vtkProcrustesAlignmentFilter()
{
  this->LandmarkTransform = vtkLandmarkTransform::New();

  this->MeanPoints = vtkPoints::New();
}

//----------------------------------------------------------------------------
// protected
vtkProcrustesAlignmentFilter::~vtkProcrustesAlignmentFilter()
{
  if(this->LandmarkTransform)
    {
    this->LandmarkTransform->Delete();
    }
  if(this->MeanPoints)
    {
    this->MeanPoints->Delete();
    }
}

//----------------------------------------------------------------------------
// Calculate the centroid of a point cloud
static inline void Centroid(vtkPoints* pd, double *cp)
{
  // Center point
  cp[0] = 0; cp[1] = 0; cp[2] = 0;

  int np = pd->GetNumberOfPoints();

  // Calculate center of shape
  for (int i = 0; i < np; i++)
    {
    double p[3];
    pd->GetPoint(i, p);
    cp[0] += p[0]; cp[1] += p[1]; cp[2] += p[2];
    }
  cp[0] /= np; cp[1] /= np; cp[2] /= np;
}

//----------------------------------------------------------------------------
// Calculate the centroid size of a point cloud
static inline double CentroidSize(vtkPoints* pd, double *cp)
{
  Centroid(pd, cp);

  double S = 0;
  for (int i = 0; i < pd->GetNumberOfPoints(); i++)
    {
    double p[3];
    pd->GetPoint(i, p);
    S += vtkMath::Distance2BetweenPoints(p,cp);
  }

  return sqrt(S);
}

//----------------------------------------------------------------------------
// Translation of point cloud. Could be done using transformations
static inline void TranslateShape(vtkPoints* pd, double *tp)
{
  for (int i = 0; i < pd->GetNumberOfPoints(); i++)
    {
    double p[3];
    pd->GetPoint(i, p);
    pd->SetPoint(i, p[0]+tp[0], p[1]+tp[1], p[2]+tp[2]);
    }
}

//----------------------------------------------------------------------------
// Scaling of point cloud. Could be done using transformations
static inline void ScaleShape(vtkPoints* pd, double S)
{
  for (int i = 0; i < pd->GetNumberOfPoints(); i++)
    {
    double p[3];
    pd->GetPoint(i, p);
    pd->SetPoint(i, p[0]*S, p[1]*S, p[2]*S);
    }
}

//----------------------------------------------------------------------------
// Normalise a point cloud to have centroid (0,0,0) and centroid size 1
static inline int NormaliseShape(vtkPoints* pd)
{
  double cp[3];
  double S = CentroidSize(pd, cp);
  if (S == 0)
    return 0;

  double tp[3];
  tp[0] = -cp[0]; tp[1] = -cp[1]; tp[2] = -cp[2];
  TranslateShape(pd, tp);
  ScaleShape(pd, 1/S);
  return 1;
}

//----------------------------------------------------------------------------
// protected
void vtkProcrustesAlignmentFilter::Execute()
{
  vtkDebugMacro(<<"Execute()");

  if(!this->vtkProcessObject::Inputs)
    {
    vtkErrorMacro(<<"No input!");
    return;
    }

  int i,v;

  const int N_SETS = this->vtkProcessObject::GetNumberOfInputs();

  // copy the inputs across
  // (really actually only the points need to be deep copied since the rest stays the same)
  for(i=0;i<N_SETS;i++)
    {
    this->GetOutput(i)->DeepCopy(this->GetInput(i));
    }

  // the number of points is determined by the first input (they must all be the same)
  const int N_POINTS = this->GetInput(0)->GetNumberOfPoints();

  vtkDebugMacro(<<"N_POINTS is " <<N_POINTS);

  if(N_POINTS == 0)
    {
    vtkErrorMacro(<<"No points!");
    return;
    }

  // all the inputs must have the same number of points to consider executing
  for(i=1;i<N_SETS;i++)
    {
    if(this->GetInput(i)->GetNumberOfPoints() != N_POINTS)
      {
      vtkErrorMacro(<<"The inputs have different numbers of points!");
      return;
      }
    }

//  vtkPoints *mean_points = vtkPoints::New();
  MeanPoints->DeepCopy(this->GetInput(0)->GetPoints());
  // our initial estimate of the mean comes from the first example in the set

  // we keep a record of the first mean to fix the orientation and scale
  // (which are otherwise undefined and the loop will not converge)
  vtkPoints *first_mean = vtkPoints::New();
  first_mean->DeepCopy(MeanPoints);

  // If the similarity transform is used, the mean shape must be normalised
  // to avoid shrinking
  if (this->LandmarkTransform->GetMode() == VTK_LANDMARK_SIMILARITY)
  {
    if (!NormaliseShape(MeanPoints)) {
      vtkErrorMacro(<<"Centroid size zero");
      return;
    }
    if (!NormaliseShape(first_mean)) {
      vtkErrorMacro(<<"Centroid size zero");
      return;
    }
  }

  // storage for the new mean that is being calculated
  vtkPoints *new_mean = vtkPoints::New();
  new_mean->SetNumberOfPoints(N_POINTS);

  // compute mean and align all the shapes to it, until convergence
  int converged=0; // bool converged=false
  int iterations=0;
  const int MAX_ITERATIONS=5;
  double difference;
  double point[3],p[3],p2[3];
  double outPoint[3];
  do { // (while not converged)

    // align each pointset with the mean
    for(i=0;i<N_SETS;i++)
      {
      this->LandmarkTransform->SetSourceLandmarks(this->GetOutput(i)->GetPoints());
      this->LandmarkTransform->SetTargetLandmarks(MeanPoints);
      this->LandmarkTransform->Update();
      for(v=0;v<N_POINTS;v++)
        {
        this->LandmarkTransform->InternalTransformPoint(
          this->GetOutput(i)->GetPoint(v), outPoint);
        this->GetOutput(i)->GetPoints()->SetPoint(v, outPoint);
        }
      }

    // compute the new mean (just average the point locations)
    for(v=0;v<N_POINTS;v++)
      {
      point[0]=0.0F;
      point[1]=0.0F;
      point[2]=0.0F;
      for(i=0;i<N_SETS;i++)
        {
        this->GetOutput(i)->GetPoint(v, p);
        point[0]+=p[0];
        point[1]+=p[1];
        point[2]+=p[2];
        }
      p[0] = point[0]/(double)N_SETS;
      p[1] = point[1]/(double)N_SETS;
      p[2] = point[2]/(double)N_SETS;
      new_mean->SetPoint(v, p);
      }

    // align the new mean with the fixed mean if the transform
    // is similarity or rigidbody. It is not yet decided what to do with affine
    if (this->LandmarkTransform->GetMode() == VTK_LANDMARK_SIMILARITY ||
        this->LandmarkTransform->GetMode() == VTK_LANDMARK_RIGIDBODY){
      this->LandmarkTransform->SetSourceLandmarks(new_mean);
      this->LandmarkTransform->SetTargetLandmarks(first_mean);
      this->LandmarkTransform->Update();
      for(v=0;v<N_POINTS;v++)
        {
        this->LandmarkTransform->InternalTransformPoint(
          new_mean->GetPoint(v), outPoint);
        new_mean->SetPoint(v, outPoint);
        }
    }

    // If the similarity transform is used, the mean shape must be normalised
    // to avoid shrinking
    if (this->LandmarkTransform->GetMode() == VTK_LANDMARK_SIMILARITY) {
      if (!NormaliseShape(new_mean)) {
        vtkErrorMacro(<<"Centroid size zero");
        return;
      }
    }

    // the new mean becomes our mean
    // compute the difference between the two
    difference = 0.0F;
    for(v=0;v<N_POINTS;v++)
      {
        new_mean->GetPoint(v, p);
        MeanPoints->GetPoint(v, p2);
        difference += vtkMath::Distance2BetweenPoints(p,p2);
        MeanPoints->SetPoint(v, p);
      }

    // test for convergence
    iterations++;
    vtkDebugMacro( << "Difference after " << iterations << " iteration(s) is: " << difference);
    if(difference<1e-6 || iterations>=MAX_ITERATIONS) {
      converged=1; // true
      }

    // The convergence test is that the sum of the distances between the
    // points on mean(t) and mean(t-1) is less than a very small number.
    // Procrustes shouldn't need more than 2 or 3 iterations but things could go wrong
    // so we impose an iteration limit to avoid getting stuck in an infinite loop.

  } while(!converged);

  if(iterations>=MAX_ITERATIONS) {
    vtkDebugMacro( << "Procrustes did not converge in  " << MAX_ITERATIONS << " iterations! Objects may not be aligned. Difference = " <<
      difference);
    // we don't throw an Error here since the shapes most probably *are* aligned, but the
    // numerical precision is worse than our convergence test anticipated.
    }
  else {
    vtkDebugMacro( << "Procrustes required " << iterations << " iterations to converge to " <<
      difference);
    }

  // clean up
  first_mean->Delete();
  new_mean->Delete();
}

//----------------------------------------------------------------------------
// public
void vtkProcrustesAlignmentFilter::SetNumberOfInputs(int n)
{
  this->vtkProcessObject::SetNumberOfInputs(n);
  this->vtkSource::SetNumberOfOutputs(n);

  // initialise the outputs
  for(int i=0;i<n;i++)
    {
    vtkPoints *points = vtkPoints::New();
    vtkPolyData *ps = vtkPolyData::New();
    ps->SetPoints(points);
    points->Delete();
    this->vtkSource::SetNthOutput(i,ps);
    ps->Delete();
    }

  // is this the right thing to be doing here? if we don't initialise the outputs here
  // then the filter crashes but vtkPolyData may not be the type of the inputs
}

//----------------------------------------------------------------------------
// public
void vtkProcrustesAlignmentFilter::SetInput(int idx,vtkPointSet* p)
{
  if(idx<0 || idx>=this->vtkProcessObject::GetNumberOfInputs())
    {
    vtkErrorMacro(<<"Index out of bounds in SetInput!");
    return;
    }

  this->vtkProcessObject::SetNthInput(idx,p);
}

//----------------------------------------------------------------------------
// public
vtkPointSet* vtkProcrustesAlignmentFilter::GetInput(int idx)
{
  if(idx<0 || idx>=this->vtkProcessObject::GetNumberOfInputs())
    {
    vtkErrorMacro(<<"Index out of bounds in GetInput!");
    return NULL;
    }

  return static_cast<vtkPointSet*>(this->vtkProcessObject::Inputs[idx]);
}

//----------------------------------------------------------------------------
// public
vtkPointSet* vtkProcrustesAlignmentFilter::GetOutput(int idx)
{
  if(idx<0 || idx>=this->vtkSource::GetNumberOfOutputs())
    {
    vtkErrorMacro(<<"Index out of bounds in GetOutput!");
    return NULL;
    }

  return static_cast<vtkPointSet*>(this->vtkSource::GetOutput(idx));
}

//----------------------------------------------------------------------------
// public
void vtkProcrustesAlignmentFilter::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);
  this->LandmarkTransform->PrintSelf(os,indent);
  this->MeanPoints->PrintSelf(os, indent);
}

<|endoftext|>


<commit_before>// Copyright Steinwurf ApS 2011-2012.
// Distributed under the "STEINWURF RESEARCH LICENSE 1.0".
// See accompanying file LICENSE.rst or
// http://www.steinwurf.com/licensing

#pragma once

#include <ctime>
#include <cstdint>
#include <cstdio>

#include <gauge/gauge.hpp>

template<class Encoder, class Decoder>
struct throughput_benchmark : public gauge::time_benchmark
{
    void init()
    {
        m_factor = 1;
        gauge::time_benchmark::init();
    }

    void start()
    {
        m_encoded_symbols = 0;
        m_recovered_symbols = 0;
        m_processed_symbols = 0;
        gauge::time_benchmark::start();
    }

    void stop()
    {
        gauge::time_benchmark::stop();
    }

    double measurement()
    {
        // Get the time spent per iteration
        double time = gauge::time_benchmark::measurement();

        gauge::config_set cs = get_current_configuration();
        std::string type = cs.get_value<std::string>("type");
        uint32_t symbol_size = cs.get_value<uint32_t>("symbol_size");

        // The number of bytes {en|de}coded
        uint64_t total_bytes = 0;

        if (type == "decoder")
        {
            total_bytes = m_recovered_symbols * symbol_size;
        }
        else if (type == "encoder")
        {
            total_bytes = m_encoded_symbols * symbol_size;
        }
        else
        {
            assert(0);
        }

        // The bytes per iteration
        uint64_t bytes =
            total_bytes / gauge::time_benchmark::iteration_count();

        return bytes / time; // MB/s for each iteration
    }

    void store_run(tables::table& results)
    {
        if (!results.has_column("goodput"))
            results.add_column("goodput");

        results.set_value("goodput", measurement());

        gauge::config_set cs = get_current_configuration();
        std::string type = cs.get_value<std::string>("type");

        if (type == "decoder")
        {
            if (!results.has_column("extra_symbols"))
                results.add_column("extra_symbols");

            uint32_t erased_symbols = cs.get_value<uint32_t>("erased_symbols");
            uint32_t extra_symbols = m_processed_symbols - erased_symbols;
            results.set_value("extra_symbols", extra_symbols);
        }
    }

    bool needs_warmup_iteration()
    {
        return false;
    }

    bool accept_measurement()
    {
        gauge::config_set cs = get_current_configuration();

        std::string type = cs.get_value<std::string>("type");

        if (type == "decoder")
        {
            // If we are benchmarking a decoder, we only accept
            // the measurement if the decoding was successful
            if (m_decoder->is_complete() == false)
            {
                return false;
            }
            // At this point, the output data should be equal to the input data
            assert(m_decoder->verify_data(m_encoder));
        }

        // Force a single iteration (repeated tests produce unstable results)
        return true;
    }

    std::string unit_text() const
    {
        return "MB/s";
    }

    void get_options(gauge::po::variables_map& options)
    {
        auto symbols = options["symbols"].as<std::vector<uint32_t> >();
        auto loss_rate = options["loss_rate"].as<std::vector<double> >();
        auto symbol_size = options["symbol_size"].as<std::vector<uint32_t> >();
        auto types = options["type"].as<std::vector<std::string> >();

        assert(symbols.size() > 0);
        assert(loss_rate.size() > 0);
        assert(symbol_size.size() > 0);
        assert(types.size() > 0);

        for (const auto& s : symbols)
        {
            for (const auto& r : loss_rate)
            {
                for (const auto& p : symbol_size)
                {
                    // Symbol size must be a multiple of 32
                    assert(p % 32 == 0);

                    for (const auto& t : types)
                    {
                        gauge::config_set cs;
                        cs.set_value<uint32_t>("symbols", s);
                        cs.set_value<uint32_t>("symbol_size", p);
                        cs.set_value<double>("loss_rate", r);
                        cs.set_value<std::string>("type", t);

                        uint32_t erased = (uint32_t)std::ceil(s * r);
                        cs.set_value<uint32_t>("erased_symbols", erased);

                        add_configuration(cs);
                    }
                }
            }
        }
    }

    void setup()
    {
        gauge::config_set cs = get_current_configuration();

        uint32_t symbols = cs.get_value<uint32_t>("symbols");
        uint32_t symbol_size = cs.get_value<uint32_t>("symbol_size");
        uint32_t erased_symbols = cs.get_value<uint32_t>("erased_symbols");

        m_encoder = std::make_shared<Encoder>(
            symbols, symbol_size, erased_symbols);
        m_decoder = std::make_shared<Decoder>(
            symbols, symbol_size, erased_symbols);
    }

    void encode_payloads()
    {
        m_encoder->encode_all();
        m_encoded_symbols += m_encoder->payload_count();
    }

    void decode_payloads()
    {
        m_processed_symbols += m_decoder->decode_all(m_encoder);

        gauge::config_set cs = get_current_configuration();
        uint32_t erased_symbols = cs.get_value<uint32_t>("erased_symbols");

        if (m_decoder->is_complete())
        {
            m_recovered_symbols += erased_symbols;
        }
    }

    /// Run the encoder
    void run_encode()
    {
        // The clock is running
        RUN
        {
            encode_payloads();
        }
    }

    /// Run the decoder
    void run_decode()
    {
        // Encode some data
        encode_payloads();

        // The clock is running
        RUN
        {
            // Decode the payloads
            decode_payloads();
        }
    }

    void run_benchmark()
    {
        gauge::config_set cs = get_current_configuration();

        std::string type = cs.get_value<std::string>("type");

        if (type == "encoder")
        {
            run_encode();
        }
        else if (type == "decoder")
        {
            run_decode();
        }
        else
        {
            assert(0);
        }
    }

protected:

    /// The encoder
    std::shared_ptr<Encoder> m_encoder;

    /// The decoder
    std::shared_ptr<Decoder> m_decoder;

    /// The number of symbols encoded
    uint32_t m_encoded_symbols;

    /// The number of symbols decoded
    uint32_t m_recovered_symbols;

    /// The number of symbols processed by the decoder
    uint32_t m_processed_symbols;

    /// Multiplication factor for payload_count
    uint32_t m_factor;
};
<commit_msg>Disable extra_symbols for strict codecs<commit_after>// Copyright Steinwurf ApS 2011-2012.
// Distributed under the "STEINWURF RESEARCH LICENSE 1.0".
// See accompanying file LICENSE.rst or
// http://www.steinwurf.com/licensing

#pragma once

#include <ctime>
#include <cstdint>
#include <cstdio>

#include <gauge/gauge.hpp>

template<class Encoder, class Decoder, bool Relaxed = false>
struct throughput_benchmark : public gauge::time_benchmark
{
    void init()
    {
        m_factor = 1;
        gauge::time_benchmark::init();
    }

    void start()
    {
        m_encoded_symbols = 0;
        m_recovered_symbols = 0;
        m_processed_symbols = 0;
        gauge::time_benchmark::start();
    }

    void stop()
    {
        gauge::time_benchmark::stop();
    }

    double measurement()
    {
        // Get the time spent per iteration
        double time = gauge::time_benchmark::measurement();

        gauge::config_set cs = get_current_configuration();
        std::string type = cs.get_value<std::string>("type");
        uint32_t symbol_size = cs.get_value<uint32_t>("symbol_size");

        // The number of bytes {en|de}coded
        uint64_t total_bytes = 0;

        if (type == "decoder")
        {
            total_bytes = m_recovered_symbols * symbol_size;
        }
        else if (type == "encoder")
        {
            total_bytes = m_encoded_symbols * symbol_size;
        }
        else
        {
            assert(0);
        }

        // The bytes per iteration
        uint64_t bytes =
            total_bytes / gauge::time_benchmark::iteration_count();

        return bytes / time; // MB/s for each iteration
    }

    void store_run(tables::table& results)
    {
        if (!results.has_column("goodput"))
            results.add_column("goodput");

        results.set_value("goodput", measurement());

        if (Relaxed)
        {
            gauge::config_set cs = get_current_configuration();
            std::string type = cs.get_value<std::string>("type");

            if (type == "decoder")
            {
                if (!results.has_column("extra_symbols"))
                    results.add_column("extra_symbols");

                uint32_t erased_symbols =
                    cs.get_value<uint32_t>("erased_symbols");
                uint32_t extra_symbols = m_processed_symbols - erased_symbols;
                results.set_value("extra_symbols", extra_symbols);
            }
        }
    }

    bool needs_warmup_iteration()
    {
        return false;
    }

    bool accept_measurement()
    {
        gauge::config_set cs = get_current_configuration();

        std::string type = cs.get_value<std::string>("type");

        if (type == "decoder")
        {
            // If we are benchmarking a decoder, we only accept
            // the measurement if the decoding was successful
            if (m_decoder->is_complete() == false)
            {
                return false;
            }
            // At this point, the output data should be equal to the input data
            assert(m_decoder->verify_data(m_encoder));
        }

        // Force a single iteration (repeated tests produce unstable results)
        return true;
    }

    std::string unit_text() const
    {
        return "MB/s";
    }

    void get_options(gauge::po::variables_map& options)
    {
        auto symbols = options["symbols"].as<std::vector<uint32_t> >();
        auto loss_rate = options["loss_rate"].as<std::vector<double> >();
        auto symbol_size = options["symbol_size"].as<std::vector<uint32_t> >();
        auto types = options["type"].as<std::vector<std::string> >();

        assert(symbols.size() > 0);
        assert(loss_rate.size() > 0);
        assert(symbol_size.size() > 0);
        assert(types.size() > 0);

        for (const auto& s : symbols)
        {
            for (const auto& r : loss_rate)
            {
                for (const auto& p : symbol_size)
                {
                    // Symbol size must be a multiple of 32
                    assert(p % 32 == 0);

                    for (const auto& t : types)
                    {
                        gauge::config_set cs;
                        cs.set_value<uint32_t>("symbols", s);
                        cs.set_value<uint32_t>("symbol_size", p);
                        cs.set_value<double>("loss_rate", r);
                        cs.set_value<std::string>("type", t);

                        uint32_t erased = (uint32_t)std::ceil(s * r);
                        cs.set_value<uint32_t>("erased_symbols", erased);

                        add_configuration(cs);
                    }
                }
            }
        }
    }

    void setup()
    {
        gauge::config_set cs = get_current_configuration();

        uint32_t symbols = cs.get_value<uint32_t>("symbols");
        uint32_t symbol_size = cs.get_value<uint32_t>("symbol_size");
        uint32_t erased_symbols = cs.get_value<uint32_t>("erased_symbols");

        m_encoder = std::make_shared<Encoder>(
            symbols, symbol_size, erased_symbols);
        m_decoder = std::make_shared<Decoder>(
            symbols, symbol_size, erased_symbols);
    }

    void encode_payloads()
    {
        m_encoder->encode_all();
        m_encoded_symbols += m_encoder->payload_count();
    }

    void decode_payloads()
    {
        m_processed_symbols += m_decoder->decode_all(m_encoder);

        gauge::config_set cs = get_current_configuration();
        uint32_t erased_symbols = cs.get_value<uint32_t>("erased_symbols");

        if (m_decoder->is_complete())
        {
            m_recovered_symbols += erased_symbols;
        }
    }

    /// Run the encoder
    void run_encode()
    {
        // The clock is running
        RUN
        {
            encode_payloads();
        }
    }

    /// Run the decoder
    void run_decode()
    {
        // Encode some data
        encode_payloads();

        // The clock is running
        RUN
        {
            // Decode the payloads
            decode_payloads();
        }
    }

    void run_benchmark()
    {
        gauge::config_set cs = get_current_configuration();

        std::string type = cs.get_value<std::string>("type");

        if (type == "encoder")
        {
            run_encode();
        }
        else if (type == "decoder")
        {
            run_decode();
        }
        else
        {
            assert(0);
        }
    }

protected:

    /// The encoder
    std::shared_ptr<Encoder> m_encoder;

    /// The decoder
    std::shared_ptr<Decoder> m_decoder;

    /// The number of symbols encoded
    uint32_t m_encoded_symbols;

    /// The number of symbols decoded
    uint32_t m_recovered_symbols;

    /// The number of symbols processed by the decoder
    uint32_t m_processed_symbols;

    /// Multiplication factor for payload_count
    uint32_t m_factor;
};
<|endoftext|>