IMathLib-ソースコード-

  • pocket
  • はてなブックマーク

#ifndef IMATHLIB_H_MATH_LINER_ALGEBRA_VECTOR_HPP
#define IMATHLIB_H_MATH_LINER_ALGEBRA_VECTOR_HPP

#include "IMathLib/math/math/math_traits.hpp"
#include "IMathLib/math/math/type_parameter.hpp"
#include "IMathLib/math/math/conj.hpp"


namespace iml {

	template <class, size_t>
	class vector;


	//ベクトル型のパラメータ
	template <class T, size_t N, class... Types>
	using vector_parameter = type_parameter<vector<T, N>, type_tuple<Types...>>;
	template <class T, size_t N, class... Params>
	struct type_parameter<vector<T, N>, type_tuple<type_parameter<T, Params>...>> {
		static_assert(N == type_tuple<type_parameter<T, Params>...>::value, "There must be N parameters.");

		using type = vector<T, N>;
		static constexpr type value = type(type_parameter<T, Params>::value...);

		template <class = std::enable_if_t<is_exist_additive_inverse_v<T>>>
		auto operator-() const { return vector_parameter<T, N, decltype(-type_parameter<T, Params>())...>(); }
		auto operator+() const { return *this; }

		template <class T, T Val, class = std::enable_if_t<(Val >= 0) && (Val < N)>>
		auto operator[](int_parameter<T, Val>) const { return at_type_t<Val, type_parameter<T, Params>...>(); }
	};

	// ベクトルにおけるスカラー演算と標準演算の十分条件の定義
	// 乗算
	template <class T1, class T2, size_t N>
	struct is_lscalar_operation_impl2<is_multipliable, T1, vector<T2, N>> : std::bool_constant<is_multipliable_v<T1, T2>> {};
	template <class T1, size_t N, class T2>
	struct is_rscalar_operation_impl2<is_multipliable, vector<T1, N>, T2> : std::bool_constant<is_multipliable_v<T1, T2>> {};
	template <class T1, class T2, size_t N>
	struct is_standard_operation_impl2<is_multipliable, vector<T1, N>, vector<T2, N>> : std::bool_constant<is_magma<mul_result_t<T1, T2>>::add_value> {};
	// 乗算代入
	template <class T1, size_t N, class T2>
	struct is_rscalar_operation_impl2<is_mul_assignable, vector<T1, N>, T2> : std::bool_constant<is_high_rank_math_type_v<mul_result_t<T1, T2>, T1>> {};


	template <class, size_t N, class = index_range_t<size_t, 0, N>>
	class vector_base;
	template <class T, size_t N, size_t... Indices>
	class vector_base<T, N, index_tuple<size_t, Indices...>> {
		template <class, size_t> friend class vector;
		template <class, size_t, class> friend class vector_base;
	protected:
		T x_m[N];
	public:
		constexpr vector_base() : x_m{} {}
		template <class... UTypes, class = std::enable_if_t<(sizeof...(UTypes) == N) && is_high_rank_math_type_v<common_math_type_t<UTypes...>, T>>>
		constexpr vector_base(const UTypes&... args) : x_m{ T(args)... } {}
		template <class U, class = std::enable_if_t<is_high_rank_math_type_v<U, T>>>
		constexpr vector_base(const vector<U, N>& v) : x_m{ v.x_m[Indices]... } {}
		template <class U, class = std::enable_if_t<is_high_rank_math_type_v<U, T>>>
		constexpr vector_base(vector<U, N>&& v) : x_m{ v.x_m[Indices]... } {}

		//単項演算
		template <class = std::enable_if_t<is_exist_additive_inverse_v<T>>>
		constexpr vector<T, N> operator-() const { return vector<T, N>(-this->x_m[Indices]...); }
		constexpr vector<T, N> operator+() const { return vector<T, N>(*this); }

		//2項演算(多重定義防止にスカラー型でない方をTとして扱い,そうでないならT1 = Tとして扱う)
		template <class T2, class = std::enable_if_t<is_addable_v<T, T2>>>
		friend constexpr auto operator+(const vector<T, N>& lhs, const vector<T2, N>& rhs) {
			return vector<add_result_t<T, T2>, N>((lhs[Indices] + rhs[Indices])...);
		}
		template <class T2, class... Types1, class... Types2, class = std::enable_if_t<is_addable_v<T, T2>>>
		friend auto operator+(vector_parameter<T, N, Types1...>, vector_parameter<T2, N, Types2...>) {
			return vector_parameter<add_result_t<T, T2>, N, decltype(Types1() + Types2())...>();
		}
		template <class T2, class = std::enable_if_t<is_subtractable_v<T, T2>>>
		friend constexpr auto operator-(const vector<T, N>& lhs, const vector<T2, N>& rhs) {
			return vector<sub_result_t<T, T2>, N>((lhs[Indices] - rhs[Indices])...);
		}
		template <class T2, class... Types1, class... Types2, class = std::enable_if_t<is_subtractable_v<T, T2>>>
		friend auto operator-(vector_parameter<T, N, Types1...>, vector_parameter<T2, N, Types2...>) {
			return vector_parameter<sub_result_t<T, T2>, N, decltype(Types1() - Types2())...>();
		}
		template <class T2, class = std::enable_if_t<is_rscalar_operation_v<is_multipliable, vector<T, N>, T2>>>
		friend constexpr auto operator*(const vector<T, N>& lhs, const T2& rhs) {
			return vector<mul_result_t<T, T2>, N>((lhs[Indices] * rhs)...);
		}
		template <class T2, class... Types, class Param, class = std::enable_if_t<is_rscalar_operation_v<is_multipliable, vector<T, N>, T2>>>
		friend auto operator*(vector_parameter<T, N, Types...>, type_parameter<T2, Param> rhs) {
			return vector_parameter<mul_result_t<T, T2>, N, decltype(Types() * rhs)...>();
		}
		template <class T1, class = std::enable_if_t<is_lscalar_operation_v<is_multipliable, T1, vector<T, N>>>>
		friend constexpr auto operator*(const T1& lhs, const vector<T, N>& rhs) {
			return vector<mul_result_t<T1, T>, N>((lhs * rhs[Indices])...);
		}
		template <class T1, class Param, class... Types, class = std::enable_if_t<is_lscalar_operation_v<is_multipliable, T1, vector<T, N>>>>
		friend auto operator*(type_parameter<T1, Param> lhs, vector_parameter<T, N, Types...>) {
			return vector_parameter<mul_result_t<T1, T>, N, decltype(lhs * Types())...>();
		}
		//内積
		template <class T2, class = std::enable_if_t<is_standard_operation_v<is_multipliable, vector<T, N>, vector<T2, N>>>>
		friend constexpr mul_result_t<T, T2> operator*(const vector<T, N>& lhs, const vector<T2, N>& rhs) {
			return (... + (lhs[Indices] * rhs[Indices]));
		}
		template <class T2, class... Types1, class... Types2, class = std::enable_if_t<is_standard_operation_v<is_multipliable, vector<T, N>, vector<T2, N>>>>
		friend auto operator*(vector_parameter<T, N, Types1...>, vector_parameter<T2, N, Types2...>) {
			return tp::sum((Types1() * Types2())...);
		}
		template <class T2, class = std::enable_if_t<is_divisible_v<T, T2>>>
		friend constexpr auto operator/(const vector<T, N>& lhs, const T2& rhs) {
			return vector<div_result_t<T, T2>, N>((lhs[Indices] / rhs)...);
		}
		template <class T2, class... Types, class Param, class = std::enable_if_t<is_divisible_v<T, T2>>>
		friend auto operator/(vector_parameter<T, N, Types...>, type_parameter<T2, Param> rhs) {
			return vector_parameter<div_result_t<T, T2>, N, decltype(Types() / rhs)...>();
		}
	};

	//ベクトル型
	template <class T, size_t N>
	class vector : public vector_base<T, N> {
		//Nは0より大きくなければならない
		static_assert(N > 0, "N must be greater than 0.");

		template <class, size_t> friend class vector;
		template <class, size_t, class> friend class vector_base;
	public:
		using vector_base<T, N>::vector_base;

		using basis_type = T;
		using iterator = linear_iterator<T>;
		using const_iterator = linear_iterator<const T>;

		template <class Other>
		struct rebind {
			using other = vector<Other, N>;
		};

		constexpr iterator begin() noexcept { return iterator(x_m); }
		constexpr const_iterator begin() const noexcept { return const_iterator(x_m); }
		constexpr iterator end() noexcept { return iterator(x_m + N); }
		constexpr const_iterator end() const noexcept { return const_iterator(x_m + N); }

		//単項演算
		using vector_base<T, N>::operator-;
		using vector_base<T, N>::operator+;
		//代入演算
		vector& operator=(const vector& v) {
			if (this != std::addressof(v)) for (size_t i = 0; i < N; ++i) this->x_m[i] = v.x_m[i];
			return *this;
		}
		template <class U, class = std::enable_if_t<is_high_rank_math_type_v<U, T>>>
		vector& operator=(const vector<U, N>& v) {
			for (size_t i = 0; i < N; ++i) this->x_m[i] = v.x_m[i];
			return *this;
		}
		template <class U, class = std::enable_if_t<is_operation<T, U, T>::add_value>>
		vector& operator+=(const vector<U, N>& v) {
			for (size_t i = 0; i < N; ++i) this->x_m[i] += v.x_m[i];
			return *this;
		}
		template <class U, class = std::enable_if_t<is_operation<T, U, T>::sub_value>>
		vector& operator-=(const vector<U, N>& v) {
			for (size_t i = 0; i < N; ++i) this->x_m[i] -= v.x_m[i];
			return *this;
		}
		template <class U, class = std::enable_if_t<is_rscalar_operation_v<is_mul_assignable, vector, U>>>
		vector& operator*=(const U& k) {
			for (size_t i = 0; i < N; ++i) this->x_m[i] *= k;
			return *this;
		}
		template <class U, class = std::enable_if_t<is_operation<T, U, T>::div_value>>
		vector& operator/=(const U& k) {
			for (size_t i = 0; i < N; ++i) this->x_m[i] /= k;
			return *this;
		}

		//添え字演算
		const constexpr T& operator[](size_t index) const { return this->x_m[index]; }
		constexpr T& operator[](size_t index) { return this->x_m[index]; }

		//ストリーム出力
		friend std::ostream& operator<<(std::ostream& os, const vector& v) {
			os << v.x_m[0];
			for (size_t i = 1; i < N; ++i) os << ',' << v.x_m[i];
			return os;
		}
		friend std::wostream& operator<<(std::wostream& os, const vector& v) {
			os << v.x_m[0];
			for (size_t i = 1; i < N; ++i) os << L',' << v.x_m[i];
			return os;
		}

		template <class T>
		constexpr linear_input<iterator> operator<<(const T& value) {
			iterator itr = this->begin();
			*itr = value; ++itr;
			return linear_input<iterator>(itr, this->end());
		}
	};


	template <class... Types>
	inline constexpr vector<common_math_type_t<Types...>, sizeof...(Types)> make_complex(Types&&... args) {
		return vector<common_math_type_t<Types...>, sizeof...(Types)>(std::forward<Types>(args)...);
	}


	//外積(T1×T2→Sが加法についてループ)
	template <class T1, class T2
		, class = std::enable_if_t<is_multipliable_v<T1, T2> && is_loop<mul_result_t<T1, T2>>::add_value>>
		inline constexpr vector<mul_result_t<T1, T2>, 3> operator%(const vector<T1, 3>& lhs, const vector<T2, 3>& rhs) {
		return vector<mul_result_t<T1, T2>, 3>(lhs[1] * rhs[2] - lhs[2] * rhs[1], lhs[2] * rhs[0] - lhs[0] * rhs[2], lhs[0] * rhs[1] - lhs[1] * rhs[0]);
	}


	//比較演算
	template <class T1, class T2, size_t N, class = std::enable_if_t<is_comparable_v<T1, T2>>>
	inline constexpr bool operator==(const vector<T1, N>& lhs, const vector<T2, N>& rhs) {
		for (size_t i = 0; i < N; ++i) if (lhs[i] != rhs[i]) return false;
		return true;
	}
	template <class T1, class T2, size_t N, class... Types1, class... Types2, class = std::enable_if_t<is_comparable_v<T1, T2>>>
	inline auto operator==(vector_parameter<T1, N, Types1...>, vector_parameter<T2, N, Types2...>) {
		constexpr bool temp = tp::sum((Types1() == Types2())...)::value == N;
		return int_parameter<bool, temp>();
	}
	template <class T1, class T2, size_t N, class = std::enable_if_t<is_comparable_v<T1, T2>>>
	inline constexpr bool operator!=(const vector<T1, N>& lhs, const vector<T2, N>& rhs) { return !(lhs == rhs); }
	template <class T1, class T2, size_t N, class... Types1, class... Types2, class = std::enable_if_t<is_comparable_v<T1, T2>>>
	inline auto operator!=(vector_parameter<T1, N, Types1...> rhs, vector_parameter<T2, N, Types2...> lhs) { return !(lhs == rhs); }


	//ベクトル型の生成
	template <class First, class... Types>
	inline constexpr vector<unwrap_reference_t<First>, sizeof...(Types) + 1> make_vector(First&& first, Types&&... args) {
		return vector<unwrap_reference_t<First>, sizeof...(Types) + 1>(std::forward<First>(first), std::forward<Types>(args)...);
	}



	//ベクトルの判定
	template <class T>
	struct is_vector_impl : std::false_type {};
	template <class T, size_t N>
	struct is_vector_impl<vector<T, N>> : std::true_type {};
	template <class T>
	struct is_vector : is_vector_impl<std::remove_cv_t<T>> {};
	template <class T>
	inline constexpr bool is_vector_v = is_vector<T>::value;

	//ベクトルの除去
	template <class T>
	struct remove_vector {
		using type = T;
	};
	template <class T, size_t N>
	struct remove_vector<vector<T, N>> {
		using type = T;
	};
	template <class T>
	using remove_vector_t = typename remove_vector<T>::type;


	//各種次元のベクトルの定義
	template <class T>
	using vector2 = vector<T, 2>;
	template <class T>
	using vector3 = vector<T, 3>;
	template <class T>
	using vector4 = vector<T, 4>;


	template <class From, class To, size_t N>
	struct is_high_rank_math_type<vector<From, N>, vector<To, N>> : is_high_rank_math_type<From, To> {};


	//加法の特性
	template <class T, size_t N>
	struct addition_traits<vector<T, N>> {
		//単位元
		template <class = std::enable_if_t<is_exist_additive_identity_v<T>>>
		static constexpr vector<T, N> identity_element() { return vector<T, N>(); }
		//結合律
		static constexpr bool associative_value = addition_traits<T>::associative_value;
		//消約律
		static constexpr bool cancellative_value = addition_traits<T>::cancellative_value;
		//可換律
		static constexpr bool commutative_value = addition_traits<T>::commutative_value;
	};
	//乗法の特性
	template <class T, size_t N>
	struct multiplication_traits<vector<T, N>> {
		//吸収元
		template <class = std::enable_if_t<is_multipliable_v<T, T> && is_exist_absorbing_element_v<T>>>
		static constexpr vector<T, N> absorbing_element() { return vector<T, N>(); }
		//結合律
		static constexpr bool associative_value = false;
		//消約律
		static constexpr bool cancellative_value = false;
		//可換律
		static constexpr bool commutative_value = multiplication_traits<T>::cancellative_value;
		//分配律
		static constexpr bool distributive_value = multiplication_traits<T>::distributive_value;
	};

	//逆元が存在するならば逆元の取得(存在しない場合は例外を出す)
	template <class T, size_t N>
	struct Inverse_element<vector<T, N>> {
		template <size_t... Indices>
		static constexpr vector<T, N> _additive_inverse_impl_(const vector<T, N>& v, index_tuple<size_t, Indices...>) {
			return vector<T, N>(additive_inverse(v[Indices])...);
		}
		static constexpr vector<T, N> _additive_inverse_(const vector<T, N>& v) {
			return _additive_inverse_impl_(v, index_range_t<size_t, 0, N>());
		}
	};


	//誤差評価
	template <class T, size_t N>
	struct Error_evaluation<vector<T, N>> {
		template <size_t... Indices>
		static constexpr vector<T, N> epsilon_impl(index_tuple<size_t, Indices...>) { return vector<T, N>(Error_evaluation<identity_t<T, Indices>>::epsilon()...); }
		static constexpr vector<T, N> epsilon() { return epsilon_impl(index_range_t<size_t, 0, N>()); }
		static constexpr bool _error_evaluation_(const vector<T, N>& x1, const vector<T, N>& x2) {
			for (size_t i = 0; i < N; ++i) if (!error_evaluation(x1[i], x2[i])) return false;
			return true;
		}
	};
}

#endif