#ifndef __COMPLEX_H #define __COMPLEX_H /** @file * @brief 複素数ライブラリ * * 複素数を定義したライブラリ。 * 多分誰が作っても似たような感じになると思われる。 */ #include "util/exception_format.h" #include "util/iostream_format.h" #if ENABLE_EXCEPTION_THROW /** * @brief 複素数に関わる例外 * * Complexクラスの例外クラス。 * 例として、演算が成立しない場合など。 * */ class ComplexException: public std::exception{ private: std::string what_str; ///< エラー内容 public: /** * コンストラクタ * * @param what_arg エラー内容 */ ComplexException(const std::string &what_arg): what_str(what_arg){} /** * デストラクタ * */ ~ComplexException() throw() {} /** * エラー内容を取得します。 * * @return (chsr *) エラー内容 */ const char *what() const throw(){ return what_str.c_str(); } }; #endif #include #ifndef PI #ifdef M_PI #define PI M_PI #else #define PI 3.14159265358973 #endif #endif /** * @brief 複素数 * * 複素数をあらわすクラスです。 * * @param FloatT 演算精度、doubleなど */ template class Complex{ private: FloatT m_Real; ///< 実部 FloatT m_Imaginary; ///< 虚部 public: /** * コンストラクタ。 * * @param real 実数部 * @param imaginary 虚数部 */ Complex(const FloatT &real, const FloatT &imaginary) : m_Real(real), m_Imaginary(imaginary){} /** * コンストラクタ。 * 虚数部は0で初期化されます。 * * @param real 実数部 */ Complex(const FloatT &real) : m_Real(real), m_Imaginary(0){} /** * コンストラクタ。 * 実数部、虚数部ともに0に初期化されます。 * */ Complex() : m_Real(0), m_Imaginary(0){} /** * デストラクタ。 * */ ~Complex(){} /** * 実数部を返します。 * * @return (FloatT) 実数部 */ FloatT &real(){return m_Real;} /** * 虚数部を返します。 * * @return (FloatT) 虚数部 */ FloatT &imaginary(){return m_Imaginary;} /** * 絶対値の二乗を返します。 * pow(real(), 2) + pow(imaginary(), 2)をしています。 * * @return (FloatT) 絶対値の二乗 * @see pow(FloatT, FloatT) */ FloatT abs2() const {return pow(m_Real, 2) + pow(m_Imaginary, 2);} /** * 絶対値を返します。 * sqrt(abs2())をしています。 * * @return (FloatT) 絶対値 * @see abs2() * @see sqrt() */ FloatT abs() const {return ::sqrt(abs2());} /** * 偏角を返します。 * * @return (double) 偏角 */ double arg() const { if((m_Real == FloatT(0)) && (m_Imaginary == FloatT(0))){ return 0; } return atan2(m_Imaginary, m_Real); } /** * 指定乗します。 * ただし定義として、複素数が * @f[ * a + b i = r e^{i \theta} * @f] * とあらわされるとき、 * @f[ * (a + b i)^{n} = r^{n} e^{i \theta n} * @f] * とします。 * * @param factor 乗数 * @return (Complex) 結果 */ Complex power(const FloatT &factor) const { if((m_Imaginary == FloatT(0)) && (m_Real >= FloatT(0))){ return Complex(pow(m_Real, factor)); }else{ FloatT _abs(pow(abs(), factor)); double _arg(arg() * factor); return Complex(_abs * cos(_arg), _abs * sin(_arg)); } } /** * 平方根を求めます。定義はpowerに従います。 * * @return (Complex) 結果 * @see power */ Complex sqrt() const { return power(FloatT(0.5)); } /** * 共役複素数を返します。 * * @return (Complex) 共役複素数 */ Complex conjugate() const { Complex result = *this; result.imaginary() *= -1; return result; } /** * 等しいかどうか調べます。 * * @return (bool) 等しい場合true */ bool operator==(const Complex &complex) const{ return m_Real == const_cast(&complex)->real() ? m_Imaginary == const_cast(&complex)->imaginary() : false; } /** * 等しくないか調べます。 * * @return (bool) 等しくない場合true */ bool operator!=(const Complex &complex) const{ return !(*this == complex); } /** * 加算を行います。破壊的です。 * * @return (Complex) 加算結果 */ Complex &operator+=(const FloatT &scalar){ m_Real += scalar; return *this; } /** * 加算を行います。 * * @return (Complex) 加算結果 */ Complex operator+(const FloatT &scalar) const{ Complex result = *this; return (result += scalar); } /** * 加算を行います。 * * @return (Complex) 加算結果 */ friend Complex operator+(const FloatT &scalar, const Complex complex){return (complex + scalar);} /** * 減算を行います。破壊的です。 * * @return (Complex) 減算結果 */ Complex &operator-=(const FloatT &scalar){return (*this) += (-scalar);} /** * 減算を行います。 * * @return (Complex) 減算結果 */ Complex operator-(const FloatT &scalar) const{return (*this) + (-scalar);} /** * 減算を行います。 * * @return (Complex) 減算結果 */ friend Complex operator-(const FloatT &scalar, const Complex complex){return (complex - scalar);} /** * 乗算を行います。破壊的です。 * * @return (Complex) 乗算結果 */ Complex &operator *=(const FloatT &scalar){ m_Real *= scalar; m_Imaginary *= scalar; return *this; } /** * 乗算を行います。 * * @return (Complex) 乗算結果 */ Complex operator*(const FloatT &scalar) const{ Complex result(*this); return (result *= scalar); } /** * 乗算を行います。 * * @return (Complex) 乗算結果 */ friend Complex operator*(const FloatT &scalar, const Complex complex){return (complex * scalar);} /** * 除算を行います。破壊的です。 * * @return (Complex) 除算結果 */ Complex &operator/=(const FloatT &scalar){return (*this) *= (1/scalar);} /** * 除算を行います。 * * @return (Complex) 除算結果 */ Complex operator/(const FloatT &scalar) const{return (*this) * (1/scalar);} /** * 単項マイナスオペレータ。 * * @return (Complex) 結果 */ Complex operator -() const{return ((*this) * -1);} /** * 加算を行います。破壊的です。 * * @return (Complex) 加算結果 */ Complex &operator+=(const Complex &complex){ m_Real += (const_cast(&complex))->real(); m_Imaginary += (const_cast(&complex))->imaginary(); return *this; } /** * 加算を行います。 * * @return (Complex) 加算結果 */ Complex operator+(const Complex &complex) const{ Complex result = *this; return (result += complex); } /** * 減算を行います。破壊的です。 * * @return (Complex) 減算結果 */ Complex &operator-=(const Complex &complex){ return ((*this) += (-complex)); } /** * 減算を行います。 * * @return (Complex) 減算結果 */ Complex operator-(const Complex &complex) const{ return ((-complex) += (*this)); } /** * 乗算を行います。 * * @return (Complex) 乗算結果 */ Complex operator*(const Complex &complex) const{ Complex result(m_Real * (const_cast(&complex))->real() - m_Imaginary * (const_cast(&complex))->imaginary(), m_Real * (const_cast(&complex))->imaginary() + m_Imaginary * (const_cast(&complex))->real()); return result; } /** * 乗算を行います。破壊的です。 * * @return (Complex) 乗算結果 */ Complex &operator*=(const Complex &complex){ Complex copy = *this; m_Real = copy.real() * (const_cast(&complex))->real() - copy.imaginary() * (const_cast(&complex))->imaginary(); m_Imaginary = copy.real() * (const_cast(&complex))->imaginary() + copy.imaginary() * (const_cast(&complex))->real(); return *this; } /** * 除算を行います。破壊的です。 * * @return (Complex) 除算結果 */ Complex &operator/=(const Complex &complex){ return (*this) *= (complex.conjugate() / complex.abs2()); } /** * 除算を行います。 * * @return (Complex) 除算結果 */ Complex operator/(const Complex &complex) const{ Complex copy = (*this); return (copy /= complex); } /** * 除算を行います。 * * @return (Complex) 除算結果 */ friend Complex operator/(const FloatT &scalar, const Complex complex){ return Complex(scalar) / complex; } #if ENABLE_IOSTREAM /** * みやすい形で複素数を出力します。 * * @param out 出力ストリーム * @param complex 出力する複素数 */ friend std::ostream &operator<<(std::ostream &out, const Complex &complex){ out << (const_cast(&complex))->real() << " + " << (const_cast(&complex))->imaginary() << "i"; return out; } #else /** * 見やすい形で出力します。 * */ void inspect(char *buffer, int buffer_size) const{ snprintf( buffer, buffer_size, "%f + %fi", (const_cast(this))->real(), (const_cast(this))->imaginary()); } #endif /** * eの指数乗を求めます。 * * @param imaginary 虚部 * @return (Complex) 結果 */ static Complex exp(const FloatT &imaginary){ return Complex(cos(imaginary), sin(imaginary)); } /** * eの指数乗を求めます。 * * @param real 実部 * @param imaginary 虚部 * @return (Complex) 結果 */ static Complex exp(const FloatT &real, const FloatT &imaginary){ return Complex::exp(imaginary) *= ::exp(real); } /** * eの指数乗を求めます。 * * @param complex 複素数 * @return (Complex) 結果 */ static Complex exp(const Complex &complex){ return Complex::exp( const_cast *>(&complex)->real(), const_cast *>(&complex)->imaginary()); } }; /** * expの複素数拡張 * * @param real 実部 * @param imaginary 虚部 * @param FloatT 演算精度 * @return (Complex) 結果 */ template inline Complex iexp(const FloatT &real, const FloatT &imaginary){ return Complex::exp(real, imaginary); } /** * expの複素数拡張 * @param imaginary 虚部 * @param FloatT 演算精度 * @return (Complex) 結果 */ template inline Complex iexp(const FloatT &imaginary){ return Complex::exp(imaginary); } /** * expの複素数拡張 * * @param complex 複素数 * @param FloatT 演算精度 * @return (Complex) 結果 */ template inline Complex exp(const Complex &complex){ return Complex::exp(complex); } /** * powの複素数拡張 * * @param complex 複素数 * @param FloatT 演算精度 * @return (Complex) 結果 */ template inline Complex pow(const Complex &complex, const FloatT &factor){ return complex.power(factor); } /** * sqrtの複素数拡張 * * @param complex 複素数 * @param FloatT 演算精度 * @return (Complex) 結果 */ template inline Complex sqrt(const Complex &complex){ return complex.sqrt(); } #ifdef USE_GSL_SUPPORT #include "param/complex_gsl.h" #endif #endif /* __COMPLEX_H */