<commit_before>#pragma once
#include "vector.hpp"
#include "angle.hpp"
#include "quaternion.hpp"

namespace frea {
	template <class T, bool A>
	struct ExpQuatT : Data<T,3,A>, op::Operator_Ne<ExpQuatT<T,A>> {
		using op_t = op::Operator_Ne<ExpQuatT<T,A>>;
		using base_t = Data<T,3,A>;
		using base_t::base_t;
		using rad_t = Radian<T>;
		using value_t = typename base_t::value_t;
		using vec_t = Vec_t<T,3,A>;
		using quat_t = QuatT<T,A>;

		ExpQuatT() = default;
		constexpr ExpQuatT(const quat_t& q) noexcept {
			constexpr auto Th = ThresholdF<value_t>(0.1);
			if(std::abs(q.w) >= 1.0-Th &&
				std::abs(q.x)+std::abs(q.y)+std::abs(q.z) <= Th)
			{
				// 無回転クォータニオンとみなす
				this->x = this->y = this->z = 0;
			} else {
				const value_t theta = std::acos(q.w);
				asVec3() = q.getAxis() * vec_t(theta);
			}
		}
		template <class T2, bool A2>
		constexpr ExpQuatT(const ExpQuatT<T2,A2>& q) noexcept:
			base_t(static_cast<const base_t&>(q))
		{}
		quat_t asQuat() const {
			const auto ret = getAngAxis();
			return quat_t::Rotation(ret.axis, ret.angle);
		}

		#define DEF_OP(op)	\
			ExpQuatT operator op (const ExpQuatT& e) const { \
				return asVec3() op e.asVec3(); \
			} \
			ExpQuatT operator op (const value_t& s) const { \
				return asVec3() op s; \
			} \
			using op_t::operator op;
		DEF_OP(+)
		DEF_OP(-)
		DEF_OP(*)
		DEF_OP(/)
		#undef DEF_OP

		bool operator == (const ExpQuatT& q) const {
			return asVec3() == q.asVec3();
		}
		value_t len_sq() const {
			return asVec3().len_sq();
		}
		value_t length() const {
			return asVec3().length();
		}
		vec_t& asVec3() noexcept {
			return reinterpret_cast<vec_t&>(*this);
		}
		const vec_t& asVec3() const noexcept {
			return reinterpret_cast<const vec_t&>(*this);
		}
		auto getAngAxis() const {
			struct {
				rad_t	angle;
				vec_t	axis;
			} ret;
			ret.axis = asVec3();
			const value_t theta = ret.axis.length();		// = (angle/2)
			if(theta < ThresholdF<value_t>(0.1)) {
				// 無回転クォータニオンとする<commit_msg>expquat: noexcept指定とコメント付加<commit_after>#pragma once
#include "vector.hpp"
#include "angle.hpp"
#include "quaternion.hpp"

namespace frea {
	template <class T, bool A>
	struct ExpQuatT : Data<T,3,A>, op::Operator_Ne<ExpQuatT<T,A>> {
		using op_t = op::Operator_Ne<ExpQuatT<T,A>>;
		using base_t = Data<T,3,A>;
		using base_t::base_t;
		using rad_t = Radian<T>;
		using value_t = typename base_t::value_t;
		using vec_t = Vec_t<T,3,A>;
		using quat_t = QuatT<T,A>;

		ExpQuatT() = default;
		constexpr ExpQuatT(const quat_t& q) {
			constexpr auto Th = ThresholdF<value_t>(0.1);
			if(std::abs(q.w) >= 1.0-Th &&
				std::abs(q.x)+std::abs(q.y)+std::abs(q.z) <= Th)
			{
				// 無回転クォータニオンとみなす
				this->x = this->y = this->z = 0;
			} else {
				const value_t theta = std::acos(q.w);
				asVec3() = q.getAxis() * vec_t(theta);
			}
		}
		//! 異なる内部形式、アラインメントからの変換
		template <class T2, bool A2>
		constexpr ExpQuatT(const ExpQuatT<T2,A2>& q) noexcept:
			base_t(static_cast<const base_t&>(q))
		{}
		quat_t asQuat() const noexcept {
			const auto ret = getAngAxis();
			return quat_t::Rotation(ret.axis, ret.angle);
		}

		#define DEF_OP(op)	\
			ExpQuatT operator op (const ExpQuatT& e) const noexcept { \
				return asVec3() op e.asVec3(); \
			} \
			ExpQuatT operator op (const value_t& s) const noexcept { \
				return asVec3() op s; \
			} \
			using op_t::operator op;
		DEF_OP(+)
		DEF_OP(-)
		DEF_OP(*)
		DEF_OP(/)
		#undef DEF_OP

		bool operator == (const ExpQuatT& q) const noexcept {
			return asVec3() == q.asVec3();
		}
		value_t len_sq() const noexcept {
			return asVec3().len_sq();
		}
		value_t length() const noexcept {
			return asVec3().length();
		}
		vec_t& asVec3() noexcept {
			return reinterpret_cast<vec_t&>(*this);
		}
		const vec_t& asVec3() const noexcept {
			return reinterpret_cast<const vec_t&>(*this);
		}
		auto getAngAxis() const noexcept {
			struct {
				rad_t	angle;
				vec_t	axis;
			} ret;
			ret.axis = asVec3();
			const value_t theta = ret.axis.length();		// = (angle/2)
			if(theta < ThresholdF<value_t>(0.1)) {
				// 無回転クォータニオンとする
{'fraction_non_alphanumeric': 0.16223535204332842, 'fraction_numerical': 0.012801575578532743, 'mean_word_length': 3.368817204301075, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5721965', 'n_tokens_mistral': 2011, 'n_tokens_neox': 1769, 'n_words': 355}