[c/c++]complex类的标准库实现

简介:

复数运算在数学领域非常重要,而且C++标准库也完备的实现了关于复数的几乎所有运算。要使用compelx类需要包含文件<complex>,并在std命名空间内引用。complex类包含了四则运算(+-*/)、符号运算(+-)、逻辑运算(==!=)、三角运算(sincostan)、双曲运算(sinhcoshtanh)、指数运算(exppow)、幂运算(loglog10)等。通过对这些基本数据类型都有的操作定义,可以complex类当做基本的数据类型来使用。对于复数运算来说还有一类很重要的反三角函数、反双曲函数,C++标准库并未实现,在boost库的boost\math\complex目录下可以找到实现。

实现:

complex类被定义和实现在<complex>文件内。

文件首先定义了三种数据结构: _C_double_complex_Dcomplex_value)、_C_float_complex_Fcomplex_value)、_C_ldouble_complex_Lcomplex_value)。这些数据结构的意义在于定义了不同类型的complex的内存存储结构。如下:

typedef struct _C_double_complex

    {   /* double complex */

    double _Val[2];

    } _C_double_complex;

typedef struct _C_float_complex

    {   /* float complex */

    float _Val[2];

    } _C_float_complex;

typedef struct _C_ldouble_complex

    {   /* long double complex */

    long double _Val[2];

    } _C_ldouble_complex;

typedef _CSTD _C_double_complex _Dcomplex_value;

typedef _CSTD _C_float_complex _Fcomplex_value;

typedef _CSTD _C_ldouble_complex _Lcomplex_value;

可以看到它的内部使用空间为2的数组来实现。然后文件前置声明了complex类的原型和三种特化版本:complex<float>complex<double>complex<long double>

template<class _Ty> class complex;

template<> class complex<float>;

template<> class complex<double>;

template<> class complex<long double>;

所以我们在使用complex类的时候就可以定义成:

complex<float> fcomplex;

complex<double> dcomplex;

complex<long double> lcomplex;

接下来定义了一个_Ctraits类,该类的作用是定义了一些基本数据类型(如doublefloatlong double等)拥有的特性(如_Isinf(是否为无穷小)、_Isnan(是否为无穷大)等)以及可实现的函数运算集合(如cos(余弦函数)、tan(正切函数)等):

        // TEMPLATE CLASS _Ctraits

template<class _Ty> class _Ctraits

    {   // complex traits for _Ty

public:

    static _Ty _Cosh(_Ty _Left, _Ty _Right);

    static short _Exp(_Ty *_Pleft, _Ty _Right, short _Exponent);

    static _Ty _Infv(_Ty);

    static bool _Isinf(_Ty _Left);

    static bool _Isnan(_Ty _Left);

    static _Ty _Nanv(_Ty);

    static _Ty _Sinh(_Ty _Left, _Ty _Right);

    static _Ty atan2(_Ty _Yval, _Ty _Xval);

    static _Ty cos(_Ty _Left);

    static _Ty exp(_Ty _Left);

    static _Ty ldexp(_Ty _Left, int _Exponent);

    static _Ty log(_Ty _Left);

    static _Ty pow(_Ty _Left, _Ty _Right);

    static _Ty sin(_Ty _Left);

    static _Ty sqrt(_Ty _Left);

    static _Ty tan(_Ty _Left);

    };

针对_Ctraits类的特化版本有三个:

        // CLASS _Ctraits<long double>

template<> class _Ctraits<long double>;

        // CLASS _Ctraits<double>

template<> class _Ctraits<double>;

        // CLASS _Ctraits<float>

template<> class _Ctraits<float>;

然后定义了一个存储模板_Complex_value,用来为complex类提供存储结构:

        // TEMPLATE CLASS _Complex_value

template<class _Ty> struct _Complex_value

    {   /* templatized complex value */

    enum {_Re = 0, _Im = 1};

    _Ty _Val[2];

    };

实际上文件已开始提到的那三个结构体(_Dcomplex_value_Fcomplex_value_Lcomplex_value)可以看做是_Complex_value的三个特化版本。

再接下来是从_Complex_value结构派生出_Complex_base类,主要提供取实部和虚部以及加减乘除的基本运算的函数。_Complex_base有两个模板参数,其中_Ty是基本数据类型,如doublefloat_Valbase是存储结构,如_Dcomplex_value_Fcomplex_value而且请注意这里有很重要的一点:_Complex_base继承自模板参数_Valbase

        // TEMPLATE CLASS _Complex_base

template<class _Ty, class _Valbase> class _Complex_base : public _Valbase

    {   // base for all complex types

public:

    typedef _Ctraits<_Ty> _Myctraits;

    typedef _Complex_base<_Ty, _Valbase> _Myt;

    typedef _Ty value_type;

 

    _Complex_base(const _Ty& _Realval, const _Ty& _Imagval);

    _Ty real(const _Ty& _Right);

    _Ty imag(const _Ty& _Right);

    _Ty real() ;

    _Ty imag() const;

protected:

    template<class _Other> inline   void _Add(const complex<_Other>& _Right);

    template<class _Other> inline   void _Sub(const complex<_Other>& _Right);

    template<class _Other> inline   void _Mul(const complex<_Other>& _Right);

    template<class _Other> inline   void _Div(const complex<_Other>& _Right);

    };

接下来有点怪异,因为complex的定义被放在了complex的特化版本之后。这里就先讲complex模板的实现。complex类继承自_Complex_base类,并且已经实现成了只有一个模板参数_Ty,但是我们知道_Complex_base类有两个模板参数,此时先前定义的那个_Complex_value模板就有作用了。然后结合后面的complex特化版本定义,就验证了我之前说过的“文件已开始提到的那三个结构体(_Dcomplex_value_Fcomplex_value_Lcomplex_value)可以看做是_Complex_value的三个特化版本”是正确的,知识没有采用明显的模板定义。至于为什么,我还没有想明白。如果读者知道为什么请告诉我一声。

// TEMPLATE CLASS complex

template<class _Ty> class complex  : public _Complex_base<_Ty, _Complex_value<_Ty> >

    {   // complex with _Ty components

public:

    typedef complex<_Ty> _Myt;

    typedef _Complex_base<_Ty, _Complex_value<_Ty> > _Mybase;

 

    complex(const _Ty& _Realval = _Ty(), const _Ty& _Imagval = _Ty());

    _Myt& operator=(const _Ty& _Right);

    template<class _Other>  complex(const complex<_Other>& _Right);

    template<class _Other>  _Myt& operator=(const complex<_Other>& _Right);

    _Myt& operator+=(const _Ty& _Right);

    _Myt& operator-=(const _Ty& _Right);

    _Myt& operator*=(const _Ty& _Right);

    _Myt& operator/=(const _Ty& _Right);

    _Myt& operator+=(const _Myt& _Right);

    _Myt& operator-=(const _Myt& _Right);

    _Myt& operator*=(const _Myt& _Right);

    _Myt& operator/=(const _Myt& _Right);

    template<class _Other> inline _Myt& operator+=(const complex<_Other>& _Right);

    template<class _Other> inline _Myt& operator-=(const complex<_Other>& _Right);

    template<class _Other> inline _Myt& operator*=(const complex<_Other>& _Right);

    template<class _Other> inline _Myt& operator/=(const complex<_Other>& _Right);

    };

接下来是complex类的三个特化版本:

complex<float>complex<double>complex<long double>

        // CLASS complex<float>

template<> class complex<float> : public _Complex_base<float, _Fcomplex_value>

    {   // complex with float components

public:

    typedef float _Ty;

    typedef complex<_Ty> _Myt;

    explicit complex(   const complex<double>&);    // defined below

    explicit complex(   const complex<long double>&);   // defined below

    complex(const _Ty& _Realval = 0, const _Ty& _Imagval = 0);

    complex(const _Fcomplex_value& _Right);

    complex(const _Dcomplex_value& _Right);

    complex(const _Lcomplex_value& _Right);

    complex<_Ty>& operator=(const _Ty& _Right);

    _Myt& operator+=(const _Ty& _Right);

    _Myt& operator-=(const _Ty& _Right);

    _Myt& operator*=(const _Ty& _Right);

    _Myt& operator/=(const _Ty& _Right);

    _Myt& operator+=(const _Myt& _Right);

    _Myt& operator-=(const _Myt& _Right);

    _Myt& operator*=(const _Myt& _Right);

    _Myt& operator/=(const _Myt& _Right);

    template<class _Other> inline   _Myt& operator=(const complex<_Other>& _Right);

    template<class _Other> inline   _Myt& operator+=(const complex<_Other>& _Right);

    template<class _Other> inline   _Myt& operator-=(const complex<_Other>& _Right);

    template<class _Other> inline   _Myt& operator*=(const complex<_Other>& _Right);

    template<class _Other> inline   _Myt& operator/=(const complex<_Other>& _Right);

    };

        // CLASS complex<double>

template<> class complex<double> : public _Complex_base<double, _Dcomplex_value>

    {   // complex with double components

public:

    typedef double _Ty;

    typedef complex<_Ty> _Myt;

    complex(    const complex<float>&); // defined below

    explicit complex(   const complex<long double>&);   // defined below

    complex(const _Ty& _Realval = 0,const _Ty& _Imagval = 0);

    complex(const _Dcomplex_value& _Right);

    complex(const _Lcomplex_value& _Right);

    complex<_Ty>& operator=(const _Ty& _Right);

    _Myt& operator+=(const _Ty& _Right);

    _Myt& operator-=(const _Ty& _Right);

    _Myt& operator*=(const _Ty& _Right);

    _Myt& operator/=(const _Ty& _Right);

    _Myt& operator+=(const _Myt& _Right);

    _Myt& operator-=(const _Myt& _Right);

    _Myt& operator*=(const _Myt& _Right);

    _Myt& operator/=(const _Myt& _Right);

    template<class _Other> inline   _Myt& operator=(const complex<_Other>& _Right);

    template<class _Other> inline   _Myt& operator+=(const complex<_Other>& _Right);

    template<class _Other> inline   _Myt& operator-=(const complex<_Other>& _Right);

    template<class _Other> inline   _Myt& operator*=(const complex<_Other>& _Right);

    template<class _Other> inline   _Myt& operator/=(const complex<_Other>& _Right);

    };

        // CLASS complex<long double>

template<> class complex<long double> : public _Complex_base<long double, _Lcomplex_value>

    {   // complex with long double components

public:

    typedef long double _Ty;

    typedef complex<_Ty> _Myt;

    complex(    const complex<float>&); // defined below

    complex(    const complex<double>&);    // defined below

    complex(const _Ty& _Realval = 0,const _Ty& _Imagval = 0);

    complex(const _Lcomplex_value& _Right);

    complex<_Ty>& operator=(const _Ty& _Right);

    _Myt& operator+=(const _Ty& _Right);

    _Myt& operator-=(const _Ty& _Right);

    _Myt& operator*=(const _Ty& _Right);

    _Myt& operator/=(const _Ty& _Right);

    _Myt& operator+=(const _Myt& _Right);

    _Myt& operator-=(const _Myt& _Right);

    _Myt& operator*=(const _Myt& _Right);

    _Myt& operator/=(const _Myt& _Right);

    template<class _Other> inline   _Myt& operator=(const complex<_Other>& _Right);

    template<class _Other> inline   _Myt& operator+=(const complex<_Other>& _Right);

    template<class _Other> inline   _Myt& operator-=(const complex<_Other>& _Right);

    template<class _Other> inline   _Myt& operator*=(const complex<_Other>& _Right);

    template<class _Other> inline   _Myt& operator/=(const complex<_Other>& _Right);

    };

    <complex>文件的最后还针对输入输出流定义了complex类的<<>>运算符。

        // TEMPLATE FUNCTION operator>>

template<class _Ty, class _Elem, class _Tr>

inline basic_istream<_Elem, _Tr>& operator>>

(basic_istream<_Elem, _Tr>& _Istr, complex<_Ty>& _Right);

        // TEMPLATE FUNCTION operator<<

template<class _Ty, class _Elem, class _Tr>

inline basic_ostream<_Elem, _Tr>& operator<<

(basic_ostream<_Elem, _Tr>& _Ostr, const complex<_Ty>& _Right);

有心的读者读到这里可能会发觉,我们找不到关于complex类的三角函数之类的运算。原来这些运算被定义在了<xcomplex>文件里。

#define _CMPLX(T)   complex<T >

#define _CTR(T) _Ctraits<T >

#define _TMPLT(T)   template<class T >

// TEMPLATE FUNCTION operator+

_TMPLT(_Ty) inline

_CMPLX(_Ty) operator+(const _CMPLX(_Ty)& _Left,  const _CMPLX(_Ty)& _Right);

_TMPLT(_Ty) inline

    _CMPLX(_Ty) operator+(const _CMPLX(_Ty)& _Left, const _Ty& _Right);

_TMPLT(_Ty) inline

    _CMPLX(_Ty) operator+(const _Ty& _Left, const _CMPLX(_Ty)& _Right);

        // TEMPLATE FUNCTION operator-

_TMPLT(_Ty) inline

    _CMPLX(_Ty) operator-(const _CMPLX(_Ty)& _Left, const _CMPLX(_Ty)& _Right);

_TMPLT(_Ty) inline

    _CMPLX(_Ty) operator-(const _CMPLX(_Ty)& _Left, const _Ty& _Right);

_TMPLT(_Ty) inline

    _CMPLX(_Ty) operator-(const _Ty& _Left, const _CMPLX(_Ty)& _Right);

        // TEMPLATE FUNCTION operator*

_TMPLT(_Ty) inline

    _CMPLX(_Ty) operator*(const _CMPLX(_Ty)& _Left, const _CMPLX(_Ty)& _Right);

_TMPLT(_Ty) inline

    _CMPLX(_Ty) operator*(const _CMPLX(_Ty)& _Left, const _Ty& _Right);

_TMPLT(_Ty) inline

    _CMPLX(_Ty) operator*(const _Ty& _Left, const _CMPLX(_Ty)& _Right);

        // TEMPLATE FUNCTION operator/

_TMPLT(_Ty) inline

    _CMPLX(_Ty) operator/(const _CMPLX(_Ty)& _Left, const _CMPLX(_Ty)& _Right);

_TMPLT(_Ty) inline

    _CMPLX(_Ty) operator/(const _CMPLX(_Ty)& _Left, const _Ty& _Right);

_TMPLT(_Ty) inline

    _CMPLX(_Ty) operator/(const _Ty& _Left, const _CMPLX(_Ty)& _Right);

        // TEMPLATE FUNCTION UNARY operator+

_TMPLT(_Ty) inline

    _CMPLX(_Ty) operator+(const _CMPLX(_Ty)& _Left);

        // TEMPLATE FUNCTION UNARY operator-

_TMPLT(_Ty) inline

    _CMPLX(_Ty) operator-(const _CMPLX(_Ty)& _Left);

        // TEMPLATE FUNCTION operator==

_TMPLT(_Ty) inline

    bool operator==(const _CMPLX(_Ty)& _Left, const _CMPLX(_Ty)& _Right);

_TMPLT(_Ty) inline

    bool operator==(const _CMPLX(_Ty)& _Left, const _Ty& _Right);

_TMPLT(_Ty) inline

    bool operator==(const _Ty& _Left, const _CMPLX(_Ty)& _Right);

        // TEMPLATE FUNCTION operator!=

_TMPLT(_Ty) inline

    bool operator!=(const _CMPLX(_Ty)& _Left, const _CMPLX(_Ty)& _Right);

_TMPLT(_Ty) inline

    bool operator!=(const _CMPLX(_Ty)& _Left, const _Ty& _Right);

_TMPLT(_Ty) inline

    bool operator!=(const _Ty& _Left, const _CMPLX(_Ty)& _Right);

        // TEMPLATE FUNCTION imag

_TMPLT(_Ty) inline

    _Ty imag(const _CMPLX(_Ty)& _Left);

        // TEMPLATE FUNCTION real

_TMPLT(_Ty) inline

    _Ty real(const _CMPLX(_Ty)& _Left);

        // TEMPLATE FUNCTION _Fabs

_TMPLT(_Ty) inline

    _Ty _Fabs(const _CMPLX(_Ty)& _Left, int *_Pexp);

        // TEMPLATE FUNCTION abs

_TMPLT(_Ty) inline

    _Ty abs(const _CMPLX(_Ty)& _Left);

        // TEMPLATE FUNCTION cosh

_TMPLT(_Ty) inline

    _CMPLX(_Ty) cosh(const _CMPLX(_Ty)& _Left);

        // TEMPLATE FUNCTION exp

_TMPLT(_Ty) inline

    _CMPLX(_Ty) exp(const _CMPLX(_Ty)& _Left);

        // TEMPLATE FUNCTION log

_TMPLT(_Ty) inline

    _CMPLX(_Ty) log(const _CMPLX(_Ty)& _Left);

        // TEMPLATE FUNCTION pow

_TMPLT(_Ty) inline

    _CMPLX(_Ty) pow(const _CMPLX(_Ty)& _Left, const _Ty& _Right);

_TMPLT(_Ty) inline

    _CMPLX(_Ty) pow(const _CMPLX(_Ty)& _Left, int _Right);

_TMPLT(_Ty) inline

    _CMPLX(_Ty) pow(const _Ty& _Left, const _CMPLX(_Ty)& _Right);

_TMPLT(_Ty) inline

    _CMPLX(_Ty) pow(const _CMPLX(_Ty)& _Left, const _CMPLX(_Ty)& _Right);

        // TEMPLATE FUNCTION sinh

_TMPLT(_Ty) inline

    _CMPLX(_Ty) sinh(const _CMPLX(_Ty)& _Left);

        // TEMPLATE FUNCTION sqrt

_TMPLT(_Ty) inline

    _CMPLX(_Ty) sqrt(const _CMPLX(_Ty)& _Left);

        // TEMPLATE FUNCTION tanh

_TMPLT(_Ty) inline

    _CMPLX(_Ty) tanh(const _CMPLX(_Ty)& _Left);

        // TEMPLATE FUNCTION arg

_TMPLT(_Ty) inline

    _Ty arg(const _CMPLX(_Ty)& _Left);

        // TEMPLATE FUNCTION conj

_TMPLT(_Ty) inline

    _CMPLX(_Ty) conj(const _CMPLX(_Ty)& _Left);

        // TEMPLATE FUNCTION cos

_TMPLT(_Ty) inline

    _CMPLX(_Ty) cos(const _CMPLX(_Ty)& _Left);

        // TEMPLATE FUNCTION log10

_TMPLT(_Ty) inline

    _CMPLX(_Ty) log10(const _CMPLX(_Ty)& _Left);

        // TEMPLATE FUNCTION norm

_TMPLT(_Ty) inline

    _Ty norm(const _CMPLX(_Ty)& _Left);

        // TEMPLATE FUNCTION polar

_TMPLT(_Ty) inline

    _CMPLX(_Ty) polar(const _Ty& _Rho, const _Ty& _Theta);

_TMPLT(_Ty) inline

    _CMPLX(_Ty) polar(const _Ty& _Rho);

        // TEMPLATE FUNCTION sin

_TMPLT(_Ty) inline

    _CMPLX(_Ty) sin(const _CMPLX(_Ty)& _Left);

        // TEMPLATE FUNCTION tan

_TMPLT(_Ty) inline

    _CMPLX(_Ty) tan(const _CMPLX(_Ty)& _Left);

转自网易博客  架构师之路

http://blog.163.com/lvan100@yeah/blog/static/68117214201251753754185/

http://blog.163.com/lvan100@yeah/blog/static/6811721420125175391253/


  • 1
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值