//: complex.h
#ifndef _COMPLEX_H_
#define _COMPLEX_H_
namespace numeric {
//////////////////////////////////////////////////////////////////////////
#include <math.h>
#define LOG10 2.30258512496948
//////////////////////////////////////////////////////////////////////////
//template<typename _tp>
//class complex;
//
//template<class _arg1, class _arg2, class _oper>
//struct _binary_expr_cc;
//////////////////////////////////////////////////////////////////////////
template<typename _tp1, typename _tp2>
struct _return_type
{
typedef double value_type;
};
template<typename _tp1>
struct _return_type<_tp1, long double>
{
typedef long double value_type;
};
template<typename _tp2>
struct _return_type<long double, _tp2>
{
typedef long double value_type;
};
template<>
struct _return_type<float, float>
{
typedef float value_type;
};
//////////////////////////////////////////////////////////////////////////
template<typename _tp>
struct constnt
{
typedef typename _tp value_type;
public:
const _tp& _m_cnst;
public:
constnt(const _tp& __t) : _m_cnst(__t) {}
//constnt(const constnt& __c) : _m_cnst(__c._m_cnst) { }
public:
inline value_type real() const
{ return _m_cnst; }
inline value_type imag() const
{ return 0; }
};
//////////////////////////////////////////////////////////////////////////
struct _abs_cc
{
template<class _arg>
static inline typename _arg::value_type
evaluate(const _arg& __a)
{ return sqrt(__a.real()*__a.real()+__a.imag()*__a.imag()); }
};
struct _arg_cc
{
template<class _arg>
static inline typename _arg::value_type
evaluate(const _arg& __a)
{ return atan2(__a.imag(), __a.real()); }
};
struct _norm_cc
{
template<class _arg>
static inline typename _arg::value_type
evaluate(const _arg& __a)
{ return (__a.real()*__a.real()+__a.imag()*__a.imag()); }
};
//////////////////////////////////////////////////////////////////////////
struct _conjg_cc
{
template<class _arg>
static inline typename _arg::value_type
real(const _arg& __a)
{ return __a.real(); }
template<class _arg>
static inline typename _arg::value_type
imag(const _arg& __a)
{ return -__a.imag(); }
};
struct _cos_cc
{
template<class _arg>
static inline typename _arg::value_type
real(const _arg& __a)
{ return cos(__a.real())*cosh(__a.imag()); }
template<class _arg>
static inline typename _arg::value_type
imag(const _arg& __a)
{ return -sin(__a.real())*sinh(__a.imag()); }
};
struct _cosh_cc
{
template<class _arg>
static inline typename _arg::value_type
real(const _arg& __a)
{ return cosh(__a.real())*cos(__a.imag()); }
template<class _arg>
static inline typename _arg::value_type
imag(const _arg& __a)
{ return sinh(__a.real())*sin(__a.imag()); }
};
struct _exp_cc
{
template<class _arg>
static inline typename _arg::value_type
real(const _arg& __a)
{
typedef typename _arg::value_type value_type;
//value_type tmp = exp(__a.real());
return exp(__a.real())*cos(__a.imag());
}
template<class _arg>
static inline typename _arg::value_type
imag(const _arg& __a)
{
typedef typename _arg::value_type value_type;
//value_type tmp = exp(__a.real());
return exp(__a.real())*sin(__a.imag());
}
};
struct _log_cc
{
template<class _arg>
static inline typename _arg::value_type
real(const _arg& __a)
{
typedef typename _arg::value_type value_type;
value_type tmp = __a.real()*__a.real()+__a.imag()*__a.imag();
return log(tmp)*0.5;
}
template<class _arg>
static inline typename _arg::value_type
imag(const _arg& __a)
{
return atan2(__a.imag(), __a.real());
}
};
struct _log10_cc
{
template<class _arg>
static inline typename _arg::value_type
real(const _arg& __a)
{
typedef typename _arg::value_type value_type;
value_type tmp = __a.real()*__a.real()+__a.imag()*__a.imag();
return log10(tmp)*0.5;
}
template<class _arg>
static inline typename _arg::value_type
imag(const _arg& __a)
{
return arg(__a)/LOG10;
}
};
struct _sin_cc
{
template<class _arg>
static inline typename _arg::value_type
real(const _arg& __a)
{ return sin(__a.real())*cosh(__a.imag()); }
template<class _arg>
static inline typename _arg::value_type
imag(const _arg& __a)
{ return cos(__a.real())*sinh(__a.imag()); }
};
struct _sinh_cc
{
template<class _arg>
static inline typename _arg::value_type
real(const _arg& __a)
{ return sinh(__a.real())*cos(__a.imag()); }
template<class _arg>
static inline typename _arg::value_type
imag(const _arg& __a)
{ return cosh(__a.real())*sin(__a.imag()); }
};
//////////////////////////////////////////////////////////////////////////
struct _pow_cc
{
template<class _arg1, class _arg2>
static inline typename _return_type<typename _arg1::value_type,
typename _arg2::value_type>::value_type
real(const _arg1& __a, const _arg2& __b)
{
//typedef typename
//_return_type<typename _arg1::value_type,
// typename _arg2::value_type
// >::value_type value_type;
//value_type t1 = log(__a.real()*__a.real()+__a.imag()*__a.imag())*0.5;
//value_type t2 = arg(__a);
//return exp(t1*__b.real()-t2*__b.imag())*cos(t1*__b.imag()+t2*__b.real());
return exp(__b*log(__a)).real();
}
template<class _arg1, class _arg2>
static inline typename _return_type<typename _arg1::value_type,
typename _arg2::value_type>::value_type
imag(const _arg1& __a, const _arg2& __b)
{
//typedef typename
//_return_type<typename _arg1::value_type,
// typename _arg2::value_type
// >::value_type value_type;
//value_type t1 = log(__a.real()*__a.real()+__a.imag()*__a.imag())*0.5;
//value_type t2 = arg(__a);
//return exp(t1*__b.real()-t2*__b.imag())*sin(t1*__b.imag()+t2*__b.real());
return exp(__b*log(__a)).imag();
}
};
//////////////////////////////////////////////////////////////////////////
struct _unary_add_cc
{
template<class _arg>
static inline typename _arg::value_type
real(const _arg& __a)
{ return __a.real(); }
template<class _arg>
static inline typename _arg::value_type
imag(const _arg& __a)
{ return __a.imag(); }
};
//////////////////////////////////////////////////////////////////////////
struct _unary_sub_cc
{
template<class _arg>
static inline typename _arg::value_type
real(const _arg& __a)
{ return -__a.real(); }
template<class _arg>
static inline typename _arg::value_type
imag(const _arg& __a)
{ return -__a.imag(); }
};
//////////////////////////////////////////////////////////////////////////
struct _binary_add_cc
{
template<class _arg1, class _arg2>
static inline typename _return_type<typename _arg1::value_type,
typename _arg2::value_type>::value_type
real(const _arg1& __a, const _arg2& __b)
{ return __a.real() + __b.real(); }
template<class _arg1, class _arg2>
static inline typename _return_type<typename _arg1::value_type,
typename _arg2::value_type>::value_type
imag(const _arg1& __a, const _arg2& __b)
{ return __a.imag() + __b.imag(); }
};
//////////////////////////////////////////////////////////////////////////
struct _binary_sub_cc
{
template<class _arg1, class _arg2>
static inline typename _return_type<typename _arg1::value_type,
typename _arg2::value_type>::value_type
real(const _arg1& __a, const _arg2& __b)
{ return __a.real() - __b.real(); }
template<class _arg1, class _arg2>
static inline typename _return_type<typename _arg1::value_type,
typename _arg2::value_type>::value_type
imag(const _arg1& __a, const _arg2& __b)
{ return __a.imag() - __b.imag(); }
};
//////////////////////////////////////////////////////////////////////////
struct _binary_mul_cc
{
template<class _arg1, class _arg2>
static inline typename _return_type<typename _arg1::value_type,
typename _arg2::value_type>::value_type
real(const _arg1& __a, const _arg2& __b)
{ return __a.real()*__b.real() - __a.imag()*__b.imag(); }
template<class _arg1, class _arg2>
static inline typename _return_type<typename _arg1::value_type,
typename _arg2::value_type>::value_type
imag(const _arg1& __a, const _arg2& __b)
{ return __a.imag()*__b.real() + __a.real()*__b.imag(); }
};
//////////////////////////////////////////////////////////////////////////
struct _binary_div_cc
{
template<class _arg1, class _arg2>
static inline typename _return_type<typename _arg1::value_type,
typename _arg2::value_type>::value_type
real(const _arg1& __a, const _arg2& __b)
{ return (__a.real()*__b.real() + __a.imag()*__b.imag())/
(__b.real()*__b.real() + __b.imag()*__b.imag()); }
template<class _arg1, class _arg2>
static inline typename _return_type<typename _arg1::value_type,
typename _arg2::value_type>::value_type
imag(const _arg1& __a, const _arg2& __b)
{ return (__a.imag()*__b.real() - __a.real()*__b.imag())/
(__b.real()*__b.real() + __b.imag()*__b.imag()); }
};
//////////////////////////////////////////////////////////////////////////
template<class _arg, class _oper>
struct _unary_expr_cc
{
typedef typename _arg::value_type value_type;
public:
const _arg& _m_arg;
public:
_unary_expr_cc(const _arg& __a) : _m_arg(__a)
{ }
inline value_type real() const
{ return _oper::real(_m_arg); }
inline value_type imag() const
{ return _oper::imag(_m_arg); }
public:
_unary_expr_cc<_unary_expr_cc<_arg,_oper>,_unary_add_cc>
operator+() const
{
typedef _unary_expr_cc<_unary_expr_cc<_arg,_oper>,
_unary_add_cc> _expr;
return _expr(*this);
}
_unary_expr_cc<_unary_expr_cc<_arg,_oper>,_unary_sub_cc>
operator-() const
{
typedef _unary_expr_cc<_unary_expr_cc<_arg,_oper>,
_unary_sub_cc> _expr;
return _expr(*this);
}
};
//////////////////////////////////////////////////////////////////////////
template<class _arg1, class _arg2, class _oper>
struct _binary_expr_cc
{
typedef typename
_return_type<typename _arg1::value_type,
typename _arg2::value_type>::value_type
value_type;
public:
const _arg1& _m_arg1;
const _arg2& _m_arg2;
public:
_binary_expr_cc(const _arg1& __a, const _arg2& __b)
: _m_arg1(__a), _m_arg2(__b)
{ }
public:
inline value_type real() const
{ return _oper::real(_m_arg1, _m_arg2); }
inline value_type imag() const
{ return _oper::imag(_m_arg1, _m_arg2); }
public:
_unary_expr_cc<_binary_expr_cc<_arg1,_arg2,_oper>,_unary_add_cc>
operator+() const
{
typedef _unary_expr_cc<_binary_expr_cc<_arg1,_arg2,_oper>,
_unary_add_cc
> _expr;
return _expr(*this);
}
_unary_expr_cc<_binary_expr_cc<_arg1,_arg2,_oper>,_unary_sub_cc>
operator-() const
{
typedef _unary_expr_cc<_binary_expr_cc<_arg1,_arg2,_oper>,
_unary_sub_cc
> _expr;
return _expr(*this);
}
};
//////////////////////////////////////////////////////////////////////////
#ifdef _DEBUG
// 在debug下,由于编译器对生成的临时变量严格按照C++标准来处理(也就是临时
// 变量生存期问题),所以需要针对常量类型进行特化。但是现在的编译器在
// release下都能对代码作出很好的优化,临时变量被优化掉了,所以没有特化
// 也能得到正确的结果!
template<typename _tp, class _arg2, class _oper>
struct _binary_expr_cc<constnt<_tp>,_arg2,_oper>
{
typedef typename
_return_type<typename _tp,
typename _arg2::value_type>::value_type
value_type;
public:
const constnt<_tp> _m_arg1;
const _arg2& _m_arg2;
public:
_binary_expr_cc(const constnt<_tp>& __a, const _arg2& __b)
: _m_arg1(__a), _m_arg2(__b)
{ //cout << "hello" << endl; }
public:
inline value_type real() const
{ return _oper::real(_m_arg1, _m_arg2); }
inline value_type imag() const
{ return _oper::imag(_m_arg1, _m_arg2); }
public:
_unary_expr_cc<_binary_expr_cc<constnt<_tp>,_arg2,_oper>,_unary_add_cc>
operator+() const
{
typedef _unary_expr_cc<_binary_expr_cc<constnt<_tp>,_arg2,_oper>,
_unary_add_cc
> _expr;
return _expr(*this);
}
};
//////////////////////////////////////////////////////////////////////////
template<class _arg1, class _tp, class _oper>
struct _binary_expr_cc<_arg1,constnt<_tp>,_oper>
{
typedef typename
_return_type<typename _arg1::value_type,
typename _tp
>::value_type value_type;
public:
const _arg1& _m_arg1;
const constnt<_tp> _m_arg2;
public:
_binary_expr_cc(const _arg1& __a, const constnt<_tp>& __b)
: _m_arg1(__a), _m_arg2(__b)
{ }
public:
inline value_type real() const
{ return _oper::real(_m_arg1, _m_arg2); }
inline value_type imag() const
{ return _oper::imag(_m_arg1, _m_arg2); }
public:
_unary_expr_cc<_binary_expr_cc<_arg1,constnt<_tp>,_oper>,
_unary_add_cc
>
operator+() const
{
typedef _unary_expr_cc<_binary_expr_cc<_arg1,constnt<_tp>,_oper>,
_unary_add_cc
> _expr;
return _expr(*this);
}
_unary_expr_cc<_binary_expr_cc<_arg1,constnt<_tp>,_oper>,
_unary_sub_cc
>
operator-() const
{
typedef _unary_expr_cc<_binary_expr_cc<_arg1,constnt<_tp>,_oper>,
_unary_sub_cc
> _expr;
return _expr(*this);
}
};
#endif // _DEBUG
//////////////////////////////////////////////////////////////////////////
template<typename _tp>
class complex
{
public:
typedef typename _tp value_type;
protected:
value_type _m_real;
value_type _m_imag;
public:
complex(const _tp& __real = _tp(), const _tp& __imag = _tp())
: _m_real(__real), _m_imag(__imag)
{
#ifdef _DEBUG
if ((typeid(value_type) != typeid(float)) &&
(typeid(value_type) != typeid(double)) &&
(typeid(value_type) != typeid(long double))) {
cout << "complex模板参数类型只支持浮点数!" << endl;
exit(0);
}
#endif // _DEBUG
}
complex(const complex& __c)
: _m_real(__c._m_real), _m_imag(__c._m_imag)
{ }
public:
template<class _arg, class _oper>
complex(const _unary_expr_cc<_arg,_oper>& __e)
: _m_real(__e.real()), _m_imag(__e.imag())
{ }
template<class _arg1, class _arg2, class _oper>
complex(const _binary_expr_cc<_arg1,_arg2,_oper>& __e)
: _m_real(__e.real()), _m_imag(__e.imag())
{ }
public:
inline complex& operator=(const complex& __c)
{
_m_real = __c.real();
_m_imag = __c.imag();
return *this;
}
template<class _arg, class _oper>
inline complex& operator=(const _unary_expr_cc<_arg,_oper>& __e)
{
_m_real = __e.real();
_m_imag = __e.imag();
return *this;
}
template<class _arg1, class _arg2, class _oper>
inline complex& operator=(const _binary_expr_cc<_arg1,_arg2,_oper>& __e)
{
_m_real = __e.real();
_m_imag = __e.imag();
return *this;
}
public:
inline complex& operator+=(const complex& __c)
{
_m_real += __c.real();
_m_imag += __c.imag();
return *this;
}
template<class _arg, class _oper>
inline complex& operator+=(const _unary_expr_cc<_arg,_oper>& __e)
{
_m_real += __e.real();
_m_imag += __e.imag();
return *this;
}
template<class _arg1, class _arg2, class _oper>
inline complex& operator+=(const _binary_expr_cc<_arg1,_arg2,_oper>& __e)
{
_m_real += __e.real();
_m_imag += __e.imag();
return *this;
}
inline complex& operator-=(const complex& __c)
{
_m_real -= __c.real();
_m_imag -= __c.imag();
return *this;
}
template<class _arg, class _oper>
inline complex& operator-=(const _unary_expr_cc<_arg,_oper>& __e)
{
_m_real -= __e.real();
_m_imag -= __e.imag();
return *this;
}
template<class _arg1, class _arg2, class _oper>
inline complex& operator-=(const _binary_expr_cc<_arg1,_arg2,_oper>& __e)
{
_m_real -= __e.real();
_m_imag -= __e.imag();
return *this;
}
inline complex& operator*=(const complex& __c)
{
static _tp rx, iy;
rx = _m_real*__c.real() - _m_imag*__c.imag();
iy = _m_real*__c.imag() + _m_imag*__c.real();
_m_real = rx;
_m_imag = iy;
return *this;
}
template<class _arg, class _oper>
inline complex& operator*=(const _unary_expr_cc<_arg,_oper>& __e)
{
static _tp rx, iy, ex, ey;
ex = __e.real();
ey = __e.imag();
rx = _m_real*ex - _m_imag*ey;
iy = _m_real*ey + _m_imag*ex;
_m_real = rx;
_m_imag = iy;
return *this;
}
template<class _arg1, class _arg2, class _oper>
inline complex& operator*=(const _binary_expr_cc<_arg1,_arg2,_oper>& __e)
{
static _tp rx, iy;
rx = _m_real*__e.real() - _m_imag*__e.imag();
iy = _m_real*__e.imag() + _m_imag*__e.real();
_m_real = rx;
_m_imag = iy;
return *this;
}
inline complex& operator/=(const complex& __c)
{
static _tp rx, iy, cx, cy, rt;
cx = __c.real();
cy = __c.imag();
rt = 1/(cx*cx+cy*cy);
rx = _m_real*cx + _m_imag*cy;
iy = -_m_real*cy + _m_imag*cx;
_m_real = rx*rt;
_m_imag = iy*rt;
return *this;
}
template<class _arg, class _oper>
inline complex& operator/=(const _unary_expr_cc<_arg,_oper>& __e)
{
static _tp rx, iy, ex, ey, rt;
ex = __e.real();
ey = __e.imag();
rt = 1/(ex*ex+ey*ey);
rx = _m_real*ex + _m_imag*ey;
iy = -_m_real*ey + _m_imag*ex;
_m_real = rx*rt;
_m_imag = iy*rt;
return *this;
}
template<class _arg1, class _arg2, class _oper>
inline complex& operator/=(const _binary_expr_cc<_arg1,_arg2,_oper>& __e)
{
static _tp rx, iy, ex, ey, rt;
ex = __e.real();
ey = __e.imag();
rt = 1/(ex*ex+ey*ey);
rx = _m_real*ex + _m_imag*ey;
iy = -_m_real*ey + _m_imag*ex;
_m_real = rx*rt;
_m_imag = iy*rt;
return *this;
}
public:
inline value_type real() const { return _m_real; }
inline value_type imag() const { return _m_imag; }
inline value_type& real() { return _m_real; }
inline value_type& imag() { return _m_imag; }
public:
_unary_expr_cc<complex<_tp>,_unary_add_cc> operator+() const
{ return _unary_expr_cc<complex<_tp>,_unary_add_cc>(*this); }
_unary_expr_cc<complex<_tp>,_unary_sub_cc> operator-() const
{ return _unary_expr_cc<complex<_tp>,_unary_sub_cc>(*this); }
};
//////////////////////////////////////////////////////////////////////////
//template<class _arg1, class _arg2>
//_binary_expr_cc<_arg1,_arg2,_add_cc>
//operator+(const _arg1& a, const _arg2& b)
//{
// typedef _binary_expr_cc<_arg1,_arg2,_add_cc> _expr;
// return _expr(a,b);
//}
#define _DEFINE_COMPLEX_BINARY_FUNC(_func, _name) \
\
template<class _arg11,class _arg12,class _oper1, \
class _arg21,class _arg22,class _oper2> \
inline \
_binary_expr_cc<_binary_expr_cc<_arg11,_arg12,_oper1>, \
_binary_expr_cc<_arg21,_arg22,_oper2>, \
_name \
> \
_func(const _binary_expr_cc<_arg11,_arg12,_oper1>& a, \
const _binary_expr_cc<_arg21,_arg22,_oper2>& b) \
{ \
typedef _binary_expr_cc<_binary_expr_cc<_arg11,_arg12,_oper1>, \
_binary_expr_cc<_arg21,_arg22,_oper2>, \
_name \
> _expr; \
return _expr(a,b); \
} \
\
template<class _arg1,class _oper1, \
class _arg21,class _arg22,class _oper2> \
inline \
_binary_expr_cc<_unary_expr_cc<_arg1,_oper1>, \
_binary_expr_cc<_arg21,_arg22,_oper2>, \
_name \
> \
_func(const _unary_expr_cc<_arg1,_oper1>& a, \
const _binary_expr_cc<_arg21,_arg22,_oper2>& b) \
{ \
typedef _binary_expr_cc<_unary_expr_cc<_arg1,_oper1>, \
_binary_expr_cc<_arg21,_arg22,_oper2>, \
_name \
> _expr; \
return _expr(a,b); \
} \
\
template<class _arg11,class _arg12,class _oper1, \
class _arg2,class _oper2> \
inline \
_binary_expr_cc<_binary_expr_cc<_arg11,_arg12,_oper1>, \
_unary_expr_cc<_arg2,_oper2>, \
_name \
> \
_func(const _binary_expr_cc<_arg11,_arg12,_oper1>& a, \
const _unary_expr_cc<_arg2,_oper2>& b) \
{ \
typedef _binary_expr_cc<_binary_expr_cc<_arg11,_arg12,_oper1>, \
_unary_expr_cc<_arg2,_oper2>, \
_name \
> _expr; \
return _expr(a,b); \
} \
\
template<class _arg1,class _oper1, \
class _arg2,class _oper2> \
inline \
_binary_expr_cc<_unary_expr_cc<_arg1,_oper1>, \
_unary_expr_cc<_arg2,_oper2>, \
_name \
> \
_func(const _unary_expr_cc<_arg1,_oper1>& a, \
const _unary_expr_cc<_arg2,_oper2>& b) \
{ \
typedef _binary_expr_cc<_unary_expr_cc<_arg1,_oper1>, \
_unary_expr_cc<_arg2,_oper2>, \
_name \
> _expr; \
return _expr(a,b); \
} \
\
template<class _arg11, class _arg12, class _oper, class _tp> \
inline \
_binary_expr_cc<_binary_expr_cc<_arg11,_arg12,_oper>, \
complex<_tp>, \
_name \
> \
_func(const _binary_expr_cc<_arg11,_arg12,_oper>& a, \
const complex<_tp>& b) \
{ \
typedef _binary_expr_cc<_binary_expr_cc<_arg11,_arg12,_oper>, \
complex<_tp>, \
_name \
> _expr; \
return _expr(a,b); \
} \
\
template<class _tp, class _arg21, class _arg22, class _oper> \
inline \
_binary_expr_cc<complex<_tp>, \
_binary_expr_cc<_arg21,_arg22,_oper>, \
_name \
> \
_func(const complex<_tp>& a, \
const _binary_expr_cc<_arg21,_arg22,_oper>& b) \
{ \
typedef _binary_expr_cc<complex<_tp>, \
_binary_expr_cc<_arg21,_arg22,_oper>, \
_name \
> _expr; \
return _expr(a,b); \
} \
\
template<class _arg11, class _arg12, class _oper, class _tp> \
inline \
_binary_expr_cc<_binary_expr_cc<_arg11,_arg12,_oper>, \
constnt<_tp>, \
_name \
> \
_func(const _binary_expr_cc<_arg11,_arg12,_oper>& a, const _tp& b) \
{ \
typedef _binary_expr_cc<_binary_expr_cc<_arg11,_arg12,_oper>, \
constnt<_tp>, \
_name \
> _expr; \
return _expr(a,b); \
} \
\
template<class _tp, class _arg21, class _arg22, class _oper> \
inline \
_binary_expr_cc<constnt<_tp>, \
_binary_expr_cc<_arg21,_arg22,_oper>, \
_name \
> \
_func(const _tp& a, const _binary_expr_cc<_arg21,_arg22,_oper>& b) \
{ \
typedef _binary_expr_cc<constnt<_tp>, \
_binary_expr_cc<_arg21,_arg22,_oper>, \
_name \
> _expr; \
return _expr(a,b); \
} \
\
template<class _arg,class _oper,class _tp> \
inline \
_binary_expr_cc<_unary_expr_cc<_arg,_oper>, \
complex<_tp>, \
_name \
> \
_func(const _unary_expr_cc<_arg,_oper>& a, const complex<_tp>& b) \
{ \
typedef _binary_expr_cc<_unary_expr_cc<_arg,_oper>, \
complex<_tp>, \
_name \
> _expr; \
return _expr(a,b); \
} \
\
template<class _tp, class _arg,class _oper> \
inline \
_binary_expr_cc<complex<_tp>, \
_unary_expr_cc<_arg,_oper>, \
_name \
> \
_func(const complex<_tp>& a, const _unary_expr_cc<_arg,_oper>& b) \
{ \
typedef _binary_expr_cc<complex<_tp>, \
_unary_expr_cc<_arg,_oper>, \
_name \
> _expr; \
return _expr(a,b); \
} \
\
template<class _arg,class _oper,class _tp> \
inline \
_binary_expr_cc<_unary_expr_cc<_arg,_oper>, \
constnt<_tp>, \
_name \
> \
_func(const _unary_expr_cc<_arg,_oper>& a, const constnt<_tp>& b) \
{ /*这个函数不常用,只是用作备用*/ \
typedef _binary_expr_cc<_unary_expr_cc<_arg,_oper>, \
constnt<_tp>, \
_name \
> _expr; \
return _expr(a,b); \
} \
\
template<class _tp, class _arg,class _oper> \
inline \
_binary_expr_cc<constnt<_tp>, \
_unary_expr_cc<_arg,_oper>, \
_name \
> \
_func(const constnt<_tp>& a, const _unary_expr_cc<_arg,_oper>& b) \
{ \
typedef _binary_expr_cc<constnt<_tp>, \
_unary_expr_cc<_arg,_oper>, \
_name \
> _expr; \
return _expr(a,b); \
} \
\
template<class _arg,class _oper,class _tp> \
inline \
_binary_expr_cc<_unary_expr_cc<_arg,_oper>, \
constnt<_tp>, \
_name \
> \
_func(const _unary_expr_cc<_arg,_oper>& a, const _tp& b) \
{ \
typedef _binary_expr_cc<_unary_expr_cc<_arg,_oper>, \
constnt<_tp>, \
_name \
> _expr; \
return _expr(a,b); \
} \
\
template<class _tp, class _arg,class _oper> \
inline \
_binary_expr_cc<constnt<_tp>, \
_unary_expr_cc<_arg,_oper>, \
_name \
> \
_func(const _tp& a, const _unary_expr_cc<_arg,_oper>& b) \
{ \
typedef _binary_expr_cc<constnt<_tp>, \
_unary_expr_cc<_arg,_oper>, \
_name \
> _expr; \
return _expr(a,b); \
} \
\
template<class _tp1, class _tp2> \
inline \
_binary_expr_cc<complex<_tp1>,complex<_tp2>,_name> \
_func(const complex<_tp1>& __a, const complex<_tp2>& __b) \
{ \
typedef _binary_expr_cc<complex<_tp1>, \
complex<_tp2>, \
_name \
> _expr; \
return _expr(__a,__b); \
} \
\
template<class _tp1, class _tp2> \
inline \
_binary_expr_cc<complex<_tp1>, \
constnt<_tp2>, \
_name \
> \
_func(const complex<_tp1>& __a, const _tp2& __b) \
{ \
typedef _binary_expr_cc<complex<_tp1>, \
constnt<_tp2>, \
_name \
> _expr; \
return _expr(__a,__b); \
} \
\
template<class _tp1, class _tp2> \
inline \
_binary_expr_cc<constnt<_tp1>, \
complex<_tp2>, \
_name \
> \
_func(const _tp1& a, const complex<_tp2>& b) \
{ \
typedef _binary_expr_cc<constnt<_tp1>, \
complex<_tp2>, \
_name \
> _expr; \
return _expr(a,b); \
}
_DEFINE_COMPLEX_BINARY_FUNC(operator+, _binary_add_cc)
_DEFINE_COMPLEX_BINARY_FUNC(operator-, _binary_sub_cc)
_DEFINE_COMPLEX_BINARY_FUNC(operator*, _binary_mul_cc)
_DEFINE_COMPLEX_BINARY_FUNC(operator/, _binary_div_cc)
_DEFINE_COMPLEX_BINARY_FUNC( pow, _pow_cc)
//////////////////////////////////////////////////////////////////////////
#define _DEFINE_COMPLEX_UNARY_FUNC(_func, _name) \
\
template<class _arg1, class _arg2, class _oper> \
_unary_expr_cc<_binary_expr_cc<_arg1,_arg2,_oper>, \
_name \
> \
_func(const _binary_expr_cc<_arg1,_arg2,_oper>& __e) \
{ \
typedef _unary_expr_cc<_binary_expr_cc<_arg1,_arg2,_oper>, \
_name \
> _expr; \
return _expr(__e); \
} \
\
template<class _arg, class _oper> \
_unary_expr_cc<_unary_expr_cc<_arg,_oper>, \
_name \
> \
_func(const _unary_expr_cc<_arg,_oper>& __e) \
{ \
typedef _unary_expr_cc<_unary_expr_cc<_arg,_oper>, \
_name \
> _expr; \
return _expr(__e); \
} \
\
template<class _tp> \
_unary_expr_cc<complex<_tp>, \
_name \
> \
_func(const complex<_tp>& __c) \
{ \
typedef _unary_expr_cc<complex<_tp>, \
_name \
> _expr; \
return _expr(__c); \
}
_DEFINE_COMPLEX_UNARY_FUNC( cos, _cos_cc)
_DEFINE_COMPLEX_UNARY_FUNC( cosh, _cosh_cc)
_DEFINE_COMPLEX_UNARY_FUNC( exp, _exp_cc)
_DEFINE_COMPLEX_UNARY_FUNC( log, _log_cc)
_DEFINE_COMPLEX_UNARY_FUNC(log10, _log10_cc)
_DEFINE_COMPLEX_UNARY_FUNC( sin, _sin_cc)
_DEFINE_COMPLEX_UNARY_FUNC( sinh, _sinh_cc)
//////////////////////////////////////////////////////////////////////////
#define _DEFINE_COMPLEX_UNARY_FUNC_EX(_func, _name) \
\
template<class _arg1, class _arg2, class _oper> \
typename _return_type<typename _arg1::value_type, \
typename _arg2::value_type \
>::value_type \
_func(const _binary_expr_cc<_arg1,_arg2,_oper>& __e) \
{ \
return _name::evaluate(__e); \
} \
\
template<class _arg, class _oper> \
typename _arg::value_type \
_func(const _unary_expr_cc<_arg,_oper>& __e) \
{ \
return _name::evaluate(__e); \
} \
\
template<typename _tp> \
typename _tp \
_func(const complex<_tp>& __c) \
{ \
return _name::evaluate(__c); \
}
_DEFINE_COMPLEX_UNARY_FUNC_EX( abs, _abs_cc)
_DEFINE_COMPLEX_UNARY_FUNC_EX( arg, _arg_cc)
_DEFINE_COMPLEX_UNARY_FUNC_EX(norm, _norm_cc)
//////////////////////////////////////////////////////////////////////////
}
#endif // _COMPLEX_H_
// test.cpp
#include <ctime>
#include <iostream>
using namespace std;
//#include <complex>
//using namespace std;
#include "complex.h"
using namespace numeric;
void main()
{
complex<double> c1(1,1), c2(2,2), c3(3,3), c4(4,4), c5(5,5), cc(0,0);
double d = 1.2, rx = 0, iy = 0;
clock_t time = clock();
for (int i=0; i<10000; ++i) {
for (int j=0; j<10000; ++j) {
// 由于被编译器的循环优化会优化=,所以采用@=
cc *= cos(d+(c1+c2)+c3);
}
}
time = clock() - time;
cout << (double)time/CLK_TCK << endl;
cout << '(' << rx
<< ',' << iy
<< ')' << endl;
cout << '(' << cc.real()
<< ',' << cc.imag()
<< ')' << endl;
}
/*************************************************************************
程序分别用intel c++ compiler 8.0, vc7.1和gcc 3.3.3编译。其中icc80和vc71
顺利编译通过,gcc编译出错。
首先用intel的编译器来测试程序:
(1) 简单运算(+,-,*,/,=,+=,-=,*=,/=)
通过测试发现,它在+、-及+=、-=上的效率约是compaq visual fortran 6.5
的complex类型的两倍多。而在稍微复杂的*、/、*=、/=上,它的效率要高出
cvf好多。
(2) 函数计算(cos, sin, exp, log)
这些函数计算与cvf相比仍然约是两倍多(fortran没有log10、sinh和cosh)。
(3) pow函数
在测试的时候发现一个有趣的问题:intel编译器在处理pow函数时对数据非常
敏感。比如申明
complex<double> c1(1,1),c2(2,2),c3(3,3),cc(0,0);
double d = 1.2;
然后计算下面语句10000*10000次
cc += pow(d+c1+c2,c3);
如果将c2(2,2)的虚部改为任何不为2的数,对比两次计算耗时,可以发现两者
差别居然有近70倍。
fortan没有pow函数,但是pow(x,y)可以表达成exp(y*log(x))。
使用vs71编译器来测试程序:
(1) 简单运算(+,-,*,/,=,+=,-=,*=,/=)
编译出的程序运行效率和visual fortran差不多,+=和-=稍微低于fortran,而
*=则约是fortran的1/3,但是/=居然有fortran的两倍。
(2) 函数计算(cos, sin, exp, sinh, cosh)
使用@=(@可以是+、-、*、/)运算符时,计算的效率和stl的complex没什么差别。
(3) 函数(log, log10)
这两个函数与(2)中的函数表现差不多,但是如果将@=(+=或-=)中的一个赋值
表达式注释掉,效率就会高出很多,但这个方法对(2)中的函数不管用。
(4) 函数(pow)
这个函数如果直接使用@=的话,也和stl的complex类差不多。但是(3)中的方法对
它也有效,更有意思的地方是——如果在循环中直接赋值:
cc.real() += pow(d+c1+c2,c3).real();
cc.imag() += pow(d+c1+c2,c3).imag();
这样得到的效率居然是fortran的两倍多。但是这种方法对(3)(2)都不管用。
*************************************************************************/
本文地址:http://com.8s8s.com/it/it24893.htm