最新版ドキュメント(英語)

c++boost.gif (8819 bytes)Class quaternion

四元数は複素数と関係深いものである。

事実、四元数は実数を基礎として構築された、小さなヒエラルキーの一部である。 この小さなヒエラルキーとは、実数の集合 、複素数の集合 、八元数の集合 及び八元数の集合 を含んだものであり、興味深い数学的特性を持っている。 主として、これらを多元体 ( division algebras ) である といい、次のような特性を持つ。 が多元体の要素であり、ゼロ以外であるならば、 であることを示している。 ただし、 は多元体の要素であるとする。 このヒエラルキーのそれぞれの要素が、実数を超越した集合である。

四元数の最も重要な側面の一つは、 (通例、三次元空間) と におけるローテーションをパラメータ表示するのに役立つ方法を提供してくれる ことである。

実質的には、四元数は単純に四つの実数 から成るものであり、 のように書く。 ここで は複素数のそれと同様のものであり、 は本質的には と同じ役割をするが全く異なるものである。

四元数の集合において加法と乗法は定義され、四元数での実数と複素数に 相当するものを一般化する。ここでの中心となる新事項は、 乗法での交換法則が成り立たない (i.e.ある四元数 , とである)。このことは、 という関係式が分かればすぐに覚えられる。

四元数やそれに類するものの詳細については、 他のドキュメント( document, errata and addenda )に記述されている。

指数関数のような伝統的な構造のものは、あまり変更せずに四元数の領域に 適用できるが、平方根を持つようなものはそうではない。

Acknowledgements

数式の編集には Nisus Writer を使用した。Jens Maurer氏には推敲とプレビューの管理で協力して戴いた。 諸々の感謝については History の部分で述べる。このライブラリを議論し 協力してくださった方々に感謝する。

Header File

インターフェースと実装を提供するのがヘッダ quaternion.h である。

Test Program

テストプログラム quaternion_test.cpp は、 float, double, long double型での八元数の特殊化のテストを行なう。 (出力の例)

BOOST_OCTONION_TEST_VERBOSEを定義していれば、さらなる出力( 出力の例 )が得られる。 もちろん(関連する行をテストプログラムに記述しない、またはコマンドラインで --log_level=messages と加えることによって)、同時に出力出来る場合のみ役立つ。 その場合、すなわち対話的に実行している場合、標準入力により入力演算子の 対話的テストのために、 (テストプログラムに大変なコーディングを施す代わりに) 付加的にBOOST_INTERACTIVE_TEST_INPUT_ITERATORを定義できる。

Synopsis

namespace boost
{
	
	namespace math
	{
	
		template<typename T> class quaternion;
		template<>           class quaternion<float>;
		template<>           class quaternion<double>; 
		template<>           class quaternion<long double>; 
		
		// operators
		
		template<typename T> inline quaternion<T> operator + (T const & lhs, quaternion<T> const & rhs);
		template<typename T> inline quaternion<T> operator + (quaternion<T> const & lhs, T const & rhs);
		template<typename T> inline quaternion<T> operator + (::std::complex<T> const & lhs, quaternion<T> const & rhs);
		template<typename T> inline quaternion<T> operator + (quaternion<T> const & lhs, ::std::complex<T> const & rhs);
		template<typename T> inline quaternion<T> operator + (quaternion<T> const & lhs, quaternion<T> const & rhs);
		
		template<typename T> inline quaternion<T> operator - (T const & lhs, quaternion<T> const & rhs);
		template<typename T> inline quaternion<T> operator - (quaternion<T> const & lhs, T const & rhs);
		template<typename T> inline quaternion<T> operator - (::std::complex<T> const & lhs, quaternion<T> const & rhs);
		template<typename T> inline quaternion<T> operator - (quaternion<T> const & lhs, ::std::complex<T> const & rhs);
		template<typename T> inline quaternion<T> operator - (quaternion<T> const & lhs, quaternion<T> const & rhs);
		
		template<typename T> inline quaternion<T> operator * (T const & lhs, quaternion<T> const & rhs);
		template<typename T> inline quaternion<T> operator * (quaternion<T> const & lhs, T const & rhs);
		template<typename T> inline quaternion<T> operator * (::std::complex<T> const & lhs, quaternion<T> const & rhs);
		template<typename T> inline quaternion<T> operator * (quaternion<T> const & lhs, ::std::complex<T> const & rhs);
		template<typename T> inline quaternion<T> operator * (quaternion<T> const & lhs, quaternion<T> const & rhs);
		
		template<typename T> inline quaternion<T> operator / (T const & lhs, quaternion<T> const & rhs);
		template<typename T> inline quaternion<T> operator / (quaternion<T> const & lhs, T const & rhs);
		template<typename T> inline quaternion<T> operator / (::std::complex<T> const & lhs, quaternion<T> const & rhs);
		template<typename T> inline quaternion<T> operator / (quaternion<T> const & lhs, ::std::complex<T> const & rhs);
		template<typename T> inline quaternion<T> operator / (quaternion<T> const & lhs, quaternion<T> const & rhs); 
		
		template<typename T> inline quaternion<T> operator + (quaternion<T> const & q);
		template<typename T> inline quaternion<T> operator - (quaternion<T> const & q); 
		
		template<typename T> inline bool operator == (T const & lhs, quaternion<T> const & rhs);
		template<typename T> inline bool operator == (quaternion<T> const & lhs, T const & rhs);
		template<typename T> inline bool operator == (::std::complex<T> const & lhs, quaternion<T> const & rhs);
		template<typename T> inline bool operator == (quaternion<T> const & lhs, ::std::complex<T> const & rhs);
		template<typename T> inline bool operator == (quaternion<T> const & lhs, quaternion<T> const & rhs);
		
		template<typename T> inline bool operator != (T const & lhs, quaternion<T> const & rhs);
		template<typename T> inline bool operator != (quaternion<T> const & lhs, T const & rhs);
		template<typename T> inline bool operator != (::std::complex<T> const & lhs, quaternion<T> const & rhs);
		template<typename T> inline bool operator != (quaternion<T> const & lhs, ::std::complex<T> const & rhs);
		template<typename T> inline bool operator != (quaternion<T> const & lhs, quaternion<T> const & rhs); 
		
		template<typename T, typename charT, class traits>
		::std::basic_istream<charT,traits> &	operator >> (::std::basic_istream<charT,traits> & is, quaternion<T> & q);
		
		template<typename T, typename charT, class traits>
		::std::basic_ostream<charT,traits> &	operator << (::std::basic_ostream<charT,traits> & os, quaternion<T> const & q);
		
		// values
		
		template<typename T>	inline T		real(quaternion<T> const & q);
		template<typename T>	inline quaternion<T>	unreal(quaternion<T> const & q);
		
		template<typename T>	inline T		sup(quaternion<T> const & q);
		template<typename T>	inline T		l1(quaternion<T> const & q);
		template<typename T>	inline T		abs(quaternion<T> const & q);
		template<typename T>	inline T		norm(quaternion<T>const  & q);
		template<typename T>	inline quaternion<T>	conj(quaternion<T> const & q);
		
		template<typename T>	inline quaternion<T>	spherical(T const & rho, T const & theta, T const & phi1, T const & phi2);
		template<typename T>	inline quaternion<T>	semipolar(T const & rho, T const & alpha, T const & theta1, T const & theta2);
		template<typename T>	inline quaternion<T>	multipolar(T const & rho1, T const & theta1, T const & rho2, T const & theta2);
		template<typename T>	inline quaternion<T>	cylindrospherical(T const & t, T const & radius, T const & longitude, T const & latitude);
		template<typename T>	inline quaternion<T>	cylindrical(T const & r, T const & angle, T const & h1, T const & h2);
		
		// transcendentals
		
		template<typename T>	inline quaternion<T>	exp(quaternion<T> const & q);
		template<typename T>	inline quaternion<T>	cos(quaternion<T> const & q);
		template<typename T>	inline quaternion<T>	sin(quaternion<T> const & q);
		template<typename T>	inline quaternion<T>	tan(quaternion<T> const & q);
		template<typename T>	inline quaternion<T>	cosh(quaternion<T> const & q);
		template<typename T>	inline quaternion<T>	sinh(quaternion<T> const & q);
		template<typename T>	inline quaternion<T>	tanh(quaternion<T> const & q);
		
		template<typename T>	quaternion<T>		pow(quaternion<T> const & q, int n);
		
	}
	
}

Template class quaternion

namespace boost
{
	namespace math
	{
	
		template<typename T>
		class quaternion
		{
		public:
			
			typedef T value_type;
			
			explicit		quaternion(T const & requested_a = T(), T const & requested_b = T(), T const & requested_c = T(), T const & requested_d = T());
			explicit		quaternion(::std::complex<T> const & z0, ::std::complex<T> const & z1 = ::std::complex<T>());
			template<typename X> explicit	quaternion(quaternion<X> const & a_recopier);
			
			T			real() const;
			quaternion<T>		unreal() const;
			T			R_component_1() const;
			T			R_component_2() const;
			T			R_component_3() const;
			T			R_component_4() const;
			::std::complex<T>	C_component_1() const;
			::std::complex<T>	C_component_2() const;
			
			quaternion<T> &	operator = (quaternion<T> const  & a_affecter);
			template<typename X>	quaternion<T> &	operator = (quaternion<X> const  & a_affecter);
			quaternion<T> &	operator = (T const  & a_affecter);
			quaternion<T> &	operator = (::std::complex<T> const & a_affecter);
			
			quaternion<T> &	operator += (T const & rhs);
			quaternion<T> &	operator += (::std::complex<T> const & rhs);
			template<typename X>	quaternion<T> &	operator += (quaternion<X> const & rhs);
			
			quaternion<T> &	operator -= (T const & rhs);
			quaternion<T> &	operator -= (::std::complex<T> const & rhs);
			template<typename X>	quaternion<T> &	operator -= (quaternion<X> const & rhs);
			
			quaternion<T> &	operator *= (T const & rhs);
			quaternion<T> &	operator *= (::std::complex<T> const & rhs);
			template<typename X>	quaternion<T> &	operator *= (quaternion<X> const & rhs);
			
			quaternion<T> &	operator /= (T const & rhs);
			quaternion<T> &	operator /= (::std::complex<T> const & rhs);
			template<typename X>	quaternion<T> &	operator /= (quaternion<X> const & rhs);
			
		};
		
	}

}

quaternion specializations

namespace boost
{
	
	namespace math
	{
		
			template<>
		class quaternion<float>
		{
		public:
			
			typedef float value_type;
			
			explicit		quaternion(float const & requested_a = 0.0f, float const & requested_b = 0.0f, float const & requested_c = 0.0f, float const & requested_d = 0.0f);
			explicit		quaternion(::std::complex<float> const & z0, ::std::complex<float> const & z1 = ::std::complex<float>());
			explicit		quaternion(quaternion<double> const & a_recopier);
			explicit		quaternion(quaternion<long double> const & a_recopier);
			
			float			real() const;
			quaternion<float>	unreal() const;
			float			R_component_1() const;
			float			R_component_2() const;
			float			R_component_3() const;
			float			R_component_4() const;
			::std::complex<float>	C_component_1() const;
			::std::complex<float>	C_component_2() const;
			
			quaternion<float> &	operator = (quaternion<float> const & a_affecter);
			template<typename X>	quaternion<float> &	operator = (quaternion<X>const  & a_affecter);
			quaternion<float> &	operator = (float const & a_affecter);
			quaternion<float> &	operator = (::std::complex<float> const & a_affecter);
			
			quaternion<float> &	operator += (float const & rhs);
			quaternion<float> &	operator += (::std::complex<float> const & rhs);
			template<typename X>	quaternion<float> &	operator += (quaternion<X> const & rhs);
			
			quaternion<float> &	operator -= (float const & rhs);
			quaternion<float> &	operator -= (::std::complex<float> const & rhs);
			template<typename X>	quaternion<float> &	operator -= (quaternion<X> const & rhs);
			
			quaternion<float> &	operator *= (float const & rhs);
			quaternion<float> &	operator *= (::std::complex<float> const & rhs);
			template<typename X>	quaternion<float> &	operator *= (quaternion<X> const & rhs);
			
			quaternion<float> &	operator /= (float const & rhs);
			quaternion<float> &	operator /= (::std::complex<float> const & rhs);
			template<typename X>	quaternion<float> &	operator /= (quaternion<X> const & rhs);
			
		};
		
		
		template<>
		class quaternion<double>
		{
		public:
			
			typedef double value_type;
			
			explicit		quaternion(double const & requested_a = 0.0, double const & requested_b = 0.0, double const & requested_c = 0.0, double const & requested_d = 0.0);
			explicit		quaternion(::std::complex<double> const & z0, ::std::complex<double> const & z1 = ::std::complex<double>());
			explicit		quaternion(quaternion<float> const & a_recopier);
			explicit		quaternion(quaternion<long double> const & a_recopier);
			
			double			real() const;
			quaternion<double>	unreal() const;
			double			R_component_1() const;
			double			R_component_2() const;
			double			R_component_3() const;
			double			R_component_4() const;
			::std::complex<double>	C_component_1() const;
			::std::complex<double>	C_component_2() const;
			
			quaternion<double> &	operator = (quaternion<double> const & a_affecter);
			template<typename X>	quaternion<double> &	operator = (quaternion<X> const & a_affecter);
			quaternion<double> &	operator = (double const & a_affecter);
			quaternion<double> &	operator = (::std::complex<double> const & a_affecter);
			
			quaternion<double> &	operator += (double const & rhs);
			quaternion<double> &	operator += (::std::complex<double> const & rhs);
			template<typename X> quaternion<double> &	operator += (quaternion<X> const & rhs);
			
			quaternion<double> &	operator -= (double const & rhs);
			quaternion<double> &	operator -= (::std::complex<double> const & rhs);
			template<typename X> quaternion<double> &	operator -= (quaternion<X> const & rhs);
			
			quaternion<double> &	operator *= (double const & rhs);
			quaternion<double> &	operator *= (::std::complex<double> const & rhs);
			template<typename X> quaternion<double> &	operator *= (quaternion<X> const & rhs);
			
			quaternion<double> &	operator /= (double const & rhs);
			quaternion<double> &	operator /= (::std::complex<double> const & rhs);
			template<typename X>	quaternion<double> &	operator /= (quaternion<X> const & rhs);
			
		};
		
		
		template<>
		class quaternion<long double>
		{
		public:
			
			typedef long double value_type;
			
			explicit			quaternion(long double const & requested_a = 0.0L, long double const & requested_b = 0.0L, long double const & requested_c = 0.0L, long double const & requested_d = 0.0L);
			explicit			quaternion(	::std::complex<long double> const & z0, ::std::complex<long double> const & z1 = ::std::complex<long double>());
			explicit			quaternion(quaternion<float> const & a_recopier);
			explicit			quaternion(quaternion<double> const & a_recopier);
			
			long double			real() const;
			quaternion<long double>		unreal() const;
			long double			R_component_1() const;
			long double			R_component_2() const;
			long double			R_component_3() const;
			long double			R_component_4() const;
			::std::complex<long double>	C_component_1() const;
			::std::complex<long double>	C_component_2() const;
			
			quaternion<long double> &	operator = (quaternion<long double> const & a_affecter);
			template<typename X>	quaternion<long double> &	operator = (quaternion<X> const & a_affecter);
			quaternion<long double> &	operator = (long double const & a_affecter);
			quaternion<long double> &	operator = (::std::complex<long double> const & a_affecter);
			
			quaternion<long double> &	operator += (long double const & rhs);
			quaternion<long double> &	operator += (::std::complex<long double> const & rhs);
			template<typename X>	quaternion<long double> &	operator += (quaternion<X> const & rhs);
			
			quaternion<long double> &	operator -= (long double const & rhs);
			quaternion<long double> &	operator -= (::std::complex<long double> const & rhs);
			template<typename X>	quaternion<long double> &	operator -= (quaternion<X> const & rhs);
			
			quaternion<long double> &	operator *= (long double const & rhs);
			quaternion<long double> &	operator *= (::std::complex<long double> const & rhs);
			template<typename X>	quaternion<long double> &	operator *= (quaternion<X> const & rhs);
			
			quaternion<long double> &	operator /= (long double const & rhs);
			quaternion<long double> &	operator /= (::std::complex<long double> const & rhs);
			template<typename X>	quaternion<long double> &	operator /= (quaternion<X> const & rhs);
			
		};
		
	}
	
}

quaternion typedefs

value_type

typedef T value_type;

テンプレート版

typedef float value_type;

float型の特殊化版

typedef double value_type;

double型の特殊化版

typedef long double value_type;

long double型の特殊化版

これらにより、テンプレートが作られる型へのアクセスが容易になる。

quaternion member functions

Constructors

explicit		quaternion(T const & requested_a = T(), T const & requested_b = T(), T const & requested_c = T(), T const & requested_d = T());
explicit		quaternion(::std::complex<T> const & z0, ::std::complex<T> const & z1 = ::std::complex<T>());
template<typename X> explicit	quaternion(quaternion<X> const & a_recopier);

テンプレート版

explicit		quaternion(float const & requested_a = 0.0f, float const & requested_b = 0.0f, float const & requested_c = 0.0f, float const & requested_d = 0.0f);
explicit		quaternion(::std::complex<float> const & z0,::std::complex<float> const & z1 = ::std::complex<float>());
explicit		quaternion(quaternion<double> const & a_recopier); 
explicit		quaternion(quaternion<long double> const & a_recopier);

float型の特殊化版

explicit		quaternion(double const & requested_a = 0.0, double const & requested_b = 0.0, double const & requested_c = 0.0, double const & requested_d = 0.0);
explicit		quaternion(::std::complex<double> const & z0, ::std::complex<double> const & z1 = ::std::complex<double>());
explicit		quaternion(quaternion<float> const & a_recopier);
explicit		quaternion(quaternion<long double> const & a_recopier);

double型の特殊化版

explicit		quaternion(long double const & requested_a = 0.0L, long double const & requested_b = 0.0L, long double const & requested_c = 0.0L, long double const & requested_d = 0.0L);
explicit		quaternion(	::std::complex<long double> const & z0, ::std::complex<long double> const & z1 = ::std::complex<long double>());
explicit		quaternion(quaternion<float> const & a_recopier);
explicit		quaternion(quaternion<double> const & a_recopier);

long doubleの特殊化版

それぞれのデフォルトコンストラクタはそれぞれのコンポーネントをデフォルトの値で 初期化し (i.e. 浮動小数では、ゼロ) 、 1〜4つまでの基底型の引数をとることもできる。 また、同じ基底型を持つ、1〜2つの複素数から四元数を作るための コンストラクタもある。 特殊化版では他の2つの特殊化版からのコピーコンストラクタがあるが、 テンプレート版ではテンプレート化されたコピーコンストラクタがあり、 精度を損なう危険があるときは explicit である。 特殊化されていないもののために、基底型のコンストラクタが 発生してはならない。

(同じ型からの、)テンプレート化されていないコピーコンストラクタ、 及びデストラクタは、コンパイラが提供する。 コピーコンストラクタを変換する際には、 テンプレート化されたヘルパ関数が副名前空間"detail" で使われる。

Other member functions

T			real() const;
quaternion<T>		unreal() const;

四元数は、複素数と同様に "実部" という重要な概念を持っているが、 複素数と異なり "虚部" という重要な概念は存在しない。 その代わり、 "実部ではない部分" があり、それこそが四元数である。 また、( 複素数の場合とは対照的に )通常は単純ではない。 最初の2つの関数がこれらを返す。

T			R_component_1() const;
T			R_component_2() const;
T			R_component_3() const;
T			R_component_4() const;

四元数は4つの実数を成分として持っており、これら4つの関数がその値を返す。 それゆえに、realR_component_1 は同じ値を返す。

::std::complex<T>	C_component_1() const;
::std::complex<T>	C_component_2() const;

同様に、四元数は2つの複素数を成分として持つ。 そして前述した通り、どのような四元数 に対しても と書ける。これらの関数はそれらを返す。 q.C_component_1() の実部は q.real() と同じである。

quaternion member operators

Assignment operators

quaternion<T> & operator = (quaternion<T> const & a_affecter);
template<typename X> quaternion<T> & operator = (quaternion<X> const & a_affecter);
quaternion<T> & operator = (T const & a_affecter);
quaternion<T> & operator = (::std::complex<T> const & a_affecter);

これらは代入を行ない、必要があれば型を変換する( 例えば、基底型からの 代入では、その値は実部へと変換される。すなわち、他の成分はゼロとなる )。 特殊化版でない場合、基底型の代入演算子は例外を発生してはならない。

Other member operators

quaternion<T> &	operator += (T const & rhs)
quaternion<T> &	operator += (::std::complex<T> const & rhs);
template<typename X>	quaternion<T> &	operator += (quaternion<X> const & rhs);

これらは数学演算子 (*this)+rhs を求めて代入を行なう。 特殊化版でないものは例外 安全の強い保証を尊守している。 特殊化版では、例外の安全性を保証するために、代入まで行なう。 特殊化版でない場合、基底型の代入演算子は例外を発生してはならない。

quaternion<T> &	operator -= (T const & rhs)
quaternion<T> &	operator -= (::std::complex<T> const & rhs);
template<typename X>	quaternion<T> &	operator -= (quaternion<X> const & rhs);

これらは数学演算子 (*this)-rhs を求めて代入を行なう。 特殊化版でないものは例外 安全の強い保証を尊守している。 特殊化版では、例外の安全性を保証するために、代入まで行なう。 特殊化版でない場合、基底型の代入演算子は例外を発生してはならない。

quaternion<T> &	operator *= (T const & rhs)
quaternion<T> &	operator *= (::std::complex<T> const & rhs);
template<typename X>	quaternion<T> &	operator *= (quaternion<X> const & rhs);

これらは数学演算子 (*this)*rhs を この順序で ( 四元数では乗法の可換でないため、乗法の順序は重要である ) 求めて代入を行なう。 特殊化版でないものは例外 安全の強い保証を尊守している。 特殊化版では、例外の安全性を保証するために、代入まで行なう。 特殊化版でない場合、基底型の代入演算子は例外を発生してはならない。

quaternion<T> &	operator /= (T const & rhs)
quaternion<T> &	operator /= (::std::complex<T> const & rhs);
template<typename X>	quaternion<T> &	operator /= (quaternion<X> const & rhs);

これらは数学演算子 (*this)*inverse_of(rhs) との積を この順序で ( 八元数では乗法の可換でないため、乗法の順序は重要である ) 求めて代入を行なう。 特殊化版でないものは例外 安全の強い保証を尊守している。 特殊化版では、例外の安全性を保証するために、代入まで行なう。 特殊化版でない場合、基底型の代入演算子は例外を発生してはならない。

quaternion non-member operations

template<typename T>	inline quaternion<T>	operator + (quaternion<T> const & q);

この単項演算子はただ q を返す。

template<typename T>	inline quaternion<T>	operator - (quaternion<T> const & q);

この単項演算子は逆符合の o を返す。 This unary operator returns the opposite of q.

template<typename T>	inline quaternion<T>	operator + (T const & lhs, quaternion<T> const & rhs);
template<typename T>	inline quaternion<T>	operator + (quaternion<T> const & lhs, T const & rhs);
template<typename T>	inline quaternion<T>	operator + (::std::complex<T> const & lhs, quaternion<T> const & rhs);
template<typename T>	inline quaternion<T>	operator + (quaternion<T> const & lhs, ::std::complex<T> const & rhs);
template<typename T>	inline quaternion<T>	operator + (quaternion<T> const & lhs, quaternion<T> const & rhs);

これらの演算子は quaternion<T>(lhs) += rhs を返す。

template<typename T>	inline quaternion<T>	operator - (T const & lhs, quaternion<T> const & rhs);
template<typename T>	inline quaternion<T>	operator - (quaternion<T> const & lhs, T const & rhs);
template<typename T>	inline quaternion<T>	operator - (::std::complex<T> const & lhs, quaternion<T> const & rhs);
template<typename T>	inline quaternion<T>	operator - (quaternion<T> const & lhs, ::std::complex<T> const & rhs);
template<typename T>	inline quaternion<T>	operator - (quaternion<T> const & lhs, quaternion<T> const & rhs);

これらの演算子は quaternion<T>(lhs) -= rhs を返す。

template<typename T>	inline quaternion<T>	operator * (T const & lhs, quaternion<T> const & rhs);
template<typename T>	inline quaternion<T>	operator * (quaternion<T> const & lhs, T const & rhs);
template<typename T>	inline quaternion<T>	operator * (::std::complex<T> const & lhs, quaternion<T> const & rhs);
template<typename T>	inline quaternion<T>	operator * (quaternion<T> const & lhs, ::std::complex<T> const & rhs);
template<typename T>	inline quaternion<T>	operator * (quaternion<T> const & lhs, quaternion<T> const & rhs);

これらの演算子は quaternion<T>(lhs) *= rhs を返す。

template<typename T>	inline quaternion<T>	operator / (T const & lhs, quaternion<T> const & rhs);
template<typename T>	inline quaternion<T>	operator / (quaternion<T> const & lhs, T const & rhs);
template<typename T>	inline quaternion<T>	operator / (::std::complex<T> const & lhs, quaternion<T> const & rhs);
template<typename T>	inline quaternion<T>	operator / (quaternion<T> const & lhs, ::std::complex<T> const & rhs);
template<typename T>	inline quaternion<T>	operator / (quaternion<T> const & lhs, quaternion<T> const & rhs);

これらの演算子は quaternion<T>(lhs) /= rhs を返す。 ゼロでの除法は、もちろんエラーになる...。

template<typename T>	inline bool	operator == (T const & lhs, quaternion<T> const & rhs);
template<typename T>	inline bool	operator == (quaternion<T> const & lhs, T const & rhs);
template<typename T>	inline bool	operator == (::std::complex<T> const & lhs, quaternion<T> const & rhs);
template<typename T>	inline bool	operator == (quaternion<T> const & lhs, ::std::complex<T> const & rhs);
template<typename T>	inline bool	operator == (quaternion<T> const & lhs, quaternion<T> const & rhs);

これらは、quaternion<T>(lhs) の4つの成分と quaternion<T>(rhs) の対応成分とが等しければ、 true を返す 浮動小数点型であっても、本質的には意味が無い。

template<typename T>	inline bool	operator != (T const & lhs, quaternion<T> const & rhs);
template<typename T>	inline bool	operator != (quaternion<T> const & lhs, T const & rhs);
template<typename T>	inline bool	operator != (::std::complex<T> const & lhs, quaternion<T> const & rhs);
template<typename T>	inline bool	operator != (quaternion<T> const & lhs, ::std::complex<T> const & rhs);
template<typename T>	inline bool	operator != (quaternion<T> const & lhs, quaternion<T> const & rhs);

これらは、quaternion<T>(lhs) == quaternion<T>(rhs)false のときのみ、 true を返す。 浮動小数点型であっても、本質的には意味が無い。

template<typename T, typename charT, class traits>
::std::basic_istream<charT,traits> &	operator >> (::std::basic_istream<charT,traits> & is, quaternion<T> & q);

( T型の a, b, c, d を用いて ) 以下のような形で、四元数 q を引き出す。

a (a), (a,b), (a,b,c), (a,b,c,d) (a,(c)), (a,(c,d)), ((a)), ((a),c), ((a),(c)), ((a),(c,d)), ((a,b)), ((a,b),c), ((a,b),(c)), ((a,b),(c,d))

入力値は T に変換できなければならない。 不正な入力に出くわしたときは、 is.setstate(ios::failbit) を呼ぶ( ios::failure (27.4.5.3) が発生するかもしれない )。

返り値は isである。

可能な書式についての解説をする。 四元数は、四つの実数か一組の複素数でもって表す。 ただし、複素数は適切に書かれている場合にかぎる。 曖昧な書式の場合は、左に詰める ( 例えば (a,b) は (a,b,0,0) であり (a,0,b,0) ではない。 i.e. 二つの実数と解釈し、虚部がゼロの複素数とは解釈しない )。

template<typename T, typename charT, class traits>
::std::basic_ostream<charT,traits> &	operator << (::std::basic_ostream<charT,traits> & os, quaternion<T> const & q);

四元数 q をストリーム os へ挿入する。 これは以下の様に実装されている:

	template<typename T, typename charT, class traits>
	::std::basic_ostream<charT,traits> &	operator << (	::std::basic_ostream<charT,traits> & os,
								quaternion<T> const & q)
	{
		::std::basic_ostringstream<charT,traits>	s;
		
		s.flags(os.flags());
		s.imbue(os.getloc());
		s.precision(os.precision());
		
		s << '('		<< q.R_component_1() << ','
					<< q.R_component_2() << ','
					<< q.R_component_3() << ','
					<< q.R_component_4() << ')';
		
		return os << s.str();
	}

quaternion value operations

template<typename T>	inline T		real(quaternion<T> const & q);
template<typename T>	inline quaternion<T>	unreal(quaternion<T> const & q);

これらはそれぞれ、 q.real()q.unreal() を返す。

template<typename T>	inline quaternion<T>	conj(quaternion<T> const & q);

これは四元数の共役を返す。

template<typename T>	inline T	 	sup(quaternion<T> const & q);

これは四元数の最大ノルム ( abs(q.R_component_1())...abs(q.R_component_4()) 間の最大値) を返す。

template<typename T>	inline T	 	l1(quaternion<T> const & q);

これは四元数の1-ノルム (abs(q.R_component_1())+...+abs(q.R_component_4())) を返す。

template<typename T>	inline T	 	abs(quaternion<T> const & q);

これは四元数の大きさ ( ユークリッドノルム ) を返す。

template<typename T>	inline T		norm(quaternion<T>const  & q);

これは四元数の ( ケイリー ) ノルムを返す。 "ノルム"という言葉からユークリッドノルム ( 二次関数のようなもの ) を連想する人びとにとっては、 "ノルム"が混乱を招くものかもしれない。 四元数 ( として知られる数学的なもの ) についてのこの表現としては、 ( 大きさとして知られている ) ユークリッドノルムはケイリーノルムの 平方根である。

template<typename T>	inline quaternion<T>	spherical(T const & rho, T const & theta, T const & phi1, T const & phi2);
template<typename T>	inline quaternion<T>	semipolar(T const & rho, T const & alpha, T const & theta1, T const & theta2);
template<typename T>	inline quaternion<T>	multipolar(T const & rho1, T const & theta1, T const & rho2, T const & theta2);
template<typename T>	inline quaternion<T>	cylindrospherical(T const & t, T const & radius, T const & longitude, T const & latitude);
template<typename T>	inline quaternion<T>	cylindrical(T const & r, T const & angle, T const & h1, T const & h2);

これらは、polarが複素数を構築するように、四元数を構築する。 ただし、四元数にとって極座標が全く同等であるというわけではない。

spherical は単に polar を置換したもので、 入力として ( 明確な ) 大きさと、 三つの角度から得られる多次元球場の 点を取る。最初のシータ theta の値域はは -pi〜+pi で、 他の二つの値域は -pi/2〜+pi/2 である ( 三次元の球面座標と同様である )。 対称性と周期性から、大きさが負であったり角度が値域外の値であっても、 不都合は生じない。しかしながら、( 大きさがゼロでは角度が無視されるといった ) 特定の不都合は生じる。

cylindrical もまた三次元での通常の円筒座標を 置き換えたものである。この円筒座標は平面の極座標からのもう一つの 派生物である。最初の二つの入力は、四元数の成分である最初のCの極座標である。 三番目、四番目の入力はそれぞれ、四元数の成分である三番目、四番目の Rにあたる。

multipolarはもう一つの、極座標の一般化である。 今度は、四元数の成分である二つのCが極座標で与えられる。

cylindrospherical は四元数に特化した関数である。 これは、 R^3 における R の直積 H を考える時によく用いられる ( このように四元数の積は特殊である )。 そして、ふつうの三次元球面座標で与えられる R^3 の成分により、 この表示から四元数を作る。

semipolarは四元数に特化した、もう一つの生成子である。 引数は最初から順に、四元数の大きさ、値域0〜+pi/2の角度、 値域-pi/2〜+pi/2の角度、値域-pi/2〜+pi/2の角度である。 二番目の引数について、この角度の正弦と余弦と最初の引数の積が 四元数の二成分 C のうち最初のものの大きさとなる。 三番目と四番目はそれぞれ四元数の二成分 C の角度となる。 大抵の場合、大きさが負になったり角度が値域外であったとしても、 対称性と周期性が崩れることはない。

我々が四元数を実装したこのバージョンでは、 複雑になるのを避けるために、 複素数の座標操作関数 arg に類するものは無い。 単位四元数は三次元、及び四次元での回転に結びつけられ、 これはあまり複雑ではない。 しかし、今現在デファクトスタンダード若しくはデジュールスタンダードとなる、 転換可能な行列ライブラリが欠けている。 おそらく、さらなるバージョンアップで改善されるだろう。 その間、どのように対処すべきか例を以下に示しておく。 三次元の例四次元の例テスト

quaternion transcendentals

現在の実装では四元数のための logsqrt は 提供されておらず、powもまた指数の整数乗に制限される。 これにはいくつか理由がある。一方で、四元数への解析接続については これから徹底的に研究されなければならない(私によって、どんなことがあっても...)。 また、複素数乗の複素数(自然に定義されるが、標準的ではない)という、 標準的に考えつくナンセンンスを回避したいと思う。 このナンセンスについて話しながら、pow(0,0)が"定義された実装"と 言うのは、明らかに脳死状態だ。

しかしながら我々は、指数関数を最高位とする、超越関数をいくつか提供しよう。 著者は"閉論理式"の完璧な証明が、 その独立な考案と同様に、自分の仕事だと主張する (定式の考案は、Shoemake教授による考案のように、 以前からあるという主張がある。 また、二世紀前から知られていたかも知れない。 しかし、参考文献が無いため、 未解決のままさらなる研究が求められていた; 一方で、四元数における指数関数の定義と存在は、 もちろん、長い間知られていた事実である)。 基本的に、実係数を持ち収束するどのような指数関数も、複素数Cでの閉論理式を 考慮されており、四元数 H に変換できる。 要請があれば、さらなる改訂版で このような超越関数をさらに加えるかもしれない。 これらの関数は boost/math/special_functions/sinc.hpp boost/math/special_functions/sinhc.hpp に依存していることに注意した方がいい。

exp

template<typename T>	inline quaternion<T>	exp(quaternion<T> const & q);

四元数の指数関数を計算する。

cos

template<typename T>	inline quaternion<T>	cos(quaternion<T> const & q);

四元数の余弦関数を計算する。

sin

template<typename T>	inline quaternion<T>	sin(quaternion<T> const & q);

四元数の正弦関数を計算する。

tan

template<typename T>	inline quaternion<T>	tan(quaternion<T> const & q);

四元数の正接関数を計算する。

cosh

template<typename T>	inline quaternion<T>	cosh(quaternion<T> const & q);

四元数の双曲余弦関数を計算する。

sinh

template<typename T>	inline quaternion<T>	sinh(quaternion<T> const & q);

四元数の双曲正弦関数を計算する。

tanh

template<typename T>	inline quaternion<T>	tanh(quaternion<T> const & q);

四元数の双曲正接関数を計算する。

pow

template<typename T>	quaternion<T>		pow(quaternion<T> const & q, int n);

四元数qn乗を計算する。

History

To Do


Revised 24 Feb 2003

© Copyright Hubert Holin 2001-2003. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in all copies. This software is provided "as is" without express or implied  warranty, and with no claim as to its suitability for any purpose.


Japanese Translation Copyright (C) 2004 Mikmai Hayato<mikami_hayato at cppll.jp>.

オリジナルの、及びこの著作権表示が全ての複製の中に現れる限り、この文書の 複製、利用、変更、販売そして配布を認める。このドキュメントは「あるがまま」 に提供されており、いかなる明示的、暗黙的保証も行わない。また、 いかなる目的に対しても、その利用が適していることを関知しない。