#ifndef __COMPLEX_H #define __COMPLEX_H #include <string> #include <exception> /** * Complexクラスの例外クラス。 * 例として、演算が成立しない場合など。 * */ class ComplexException: public exception{ private: string what_str; public: ComplexException(const string &what_arg): what_str(what_arg){} ~ComplexException() throw() {} /** * エラー内容を取得します。 * * @return (chsr *) エラー内容 */ const char *what() const throw(){ return what_str.c_str(); } }; #include <ostream> #include <math.h> #ifndef PI #define PI 3.14159265358973 #endif /** * 複素数をあらわすクラスです。 * */ template <class T> class Complex{ private: T m_Real; T m_Imaginary; public: /** * コンストラクタ。 * * @param real 実数部 * @param imaginary 虚数部 */ Complex(const T &real, const T &imaginary) : m_Real(real), m_Imaginary(imaginary){} /** * コンストラクタ。 * 虚数部は0で初期化されます。 * * @param real 実数部 */ Complex(const T &real) : m_Real(real), m_Imaginary(0){} /** * コンストラクタ。 * 実数部、虚数部ともに0に初期化されます。 * */ Complex() : m_Real(0), m_Imaginary(0){} /** * デストラクタ。 * */ ~Complex(){} /** * 実数部を返します。 * * @return (T) 実数部 */ T &real(){return m_Real;} /** * 虚数部を返します。 * * @return (T) 虚数部 */ T &imaginary(){return m_Imaginary;} /** * 絶対値の二乗を返します。 * pow(real(), 2) + pow(imaginary(), 2)をしています。 * * @return (T) 絶対値の二乗 * @see pow(T, T) */ T abs2() const {return pow(m_Real, 2) + pow(m_Imaginary, 2);} /** * 絶対値を返します。 * sqrt(abs2())をしています。 * * @return (T) 絶対値 * @see abs2() * @see sqrt() */ T abs() const {return sqrt(abs2());} /** * 偏角を返します。 * * @return (double) 偏角 */ double arg() const { if(m_Real == T(0)){return m_Imaginary < T(0) ? -PI/2 : PI/2;} if(m_Real < T(0)){ return atan(m_Imaginary / m_Real) + (m_Imaginary < T(0) ? -PI : PI); }else{ return atan(m_Imaginary / m_Real); } } /** * 指定乗します。 * もし、虚数部が0でなく、かつ乗数が1以下の場合、エラーとなります。 * * @param factor 乗数 * @return (Complex<T>) 結果 * @throw ComplexException 演算が一意に成立しない場合 */ Complex<T> power(const T &factor) const throw(ComplexException){ if(m_Imaginary == T(0)){ if(m_Real < T(0)){throw ComplexException("Operation void!!");} return Complex(pow(m_Real, factor)); }else{ if(factor < T(1)){throw ComplexException("Operation void!!");} T _abs = pow(abs(), factor); double _arg = arg() * factor; return Complex(_abs * cos(_arg), _abs * sin(_arg)); } } /** * 共役複素数を返します。 * * @return (Complex<T>) 共役複素数 */ Complex<T> conjugate() const { Complex<T> result = *this; result.imaginary() *= -1; return result; } bool operator==(const Complex<T> &complex) const{ return m_Real == const_cast<Complex *>(&complex)->real() ? m_Imaginary == const_cast<Complex *>(&complex)->imaginary() : false; } bool operator!=(const Complex<T> &complex) const{ return !(*this == complex); } Complex<T> &operator+=(const T &scalar){ m_Real += scalar; return *this; } Complex<T> operator+(const T &scalar) const{ Complex<T> result = *this; return (result += scalar); } friend Complex<T> operator+(const T &scalar, const Complex<T> complex){return (complex + scalar);} Complex<T> &operator-=(const T &scalar){return (*this) += (-scalar);} Complex<T> operator-(const T &scalar) const{return (*this) + (-scalar);} friend Complex<T> operator-(const T &scalar, const Complex<T> complex){return (complex -scalar);} Complex<T> &operator *=(const T &scalar){ m_Real *= scalar; m_Imaginary *= scalar; return *this; } Complex<T> operator*(const T &scalar) const{ Complex<T> result = *this; return (result *= scalar); } friend Complex<T> operator*(const T &scalar, const Complex<T> complex){return (complex * scalar);} Complex<T> &operator/=(const T &scalar){return (*this) *= (1/scalar);} Complex<T> operator/(const T &scalar) const{return (*this) * (1/scalar);} friend Complex<T> operator/(const T &scalar, const Complex<T> complex){return (complex / scalar);} Complex<T> operator -() const{return ((*this) * -1);} Complex<T> &operator+=(const Complex<T> &complex){ m_Real += (const_cast<Complex *>(&complex))->real(); m_Imaginary += (const_cast<Complex *>(&complex))->imaginary(); return *this; } Complex<T> operator+(const Complex<T> &complex) const{ Complex<T> result = *this; return (result += complex); } Complex<T> &operator-=(const Complex<T> &complex){ return ((*this) += (-complex)); } Complex<T> operator-(const Complex<T> &complex) const{ return ((-complex) += (*this)); } Complex<T> operator*(const Complex<T> &complex) const{ Complex<T> result(m_Real * (const_cast<Complex *>(&complex))->real() -m_Imaginary * (const_cast<Complex *>(&complex))->imaginary(), m_Real * (const_cast<Complex *>(&complex))->imaginary() + m_Imaginary * (const_cast<Complex *>(&complex))->real()); return result; } Complex<T> &operator*=(const Complex<T> &complex){ Complex<T> copy = *this; m_Real = copy.real() * (const_cast<Complex *>(&complex))->real() -copy.imaginary() * (const_cast<Complex *>(&complex))->imaginary(); m_Imaginary = copy.real() * (const_cast<Complex *>(&complex))->imaginary() + copy.imaginary() * (const_cast<Complex *>(&complex))->real(); return *this; } Complex<T> &operator/=(const Complex<T> &complex){ return (*this) *= (complex.conjugate() / complex.abs2()); } Complex<T> operator/(const Complex<T> &complex) const{ Complex<T> copy = (*this); return (copy /= complex); } /** * みやすい形で複素数を出力します。 * */ friend ostream &operator<<(ostream &out, const Complex<T> &complex){ out << (const_cast<Complex *>(&complex))->real() << " + " << (const_cast<Complex *>(&complex))->imaginary() << "i"; return out; } }; #endif /* __COMPLEX_H */