#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 */