Author: | Thorsten Ottosen |
---|---|
Contact: | nesotto@cs.aau.dk |
organizations: | Dezide Aps and Aalborg University |
Date: | 2005-08-24 |
Number: | WG21/N1869 and J16/05-0129 |
Working Group: | Evolution |
Abstract
This paper provides wording for n1612 which proposed to extend the complex number facility with imaginary numbers.
Modify 26.2 as shown:
1 The header <complex> defines a class template class templates, and numerous functions for representing and manipulating complex numbers.
2 The effect of instantiating the template complex or imaginary for any type other than float, double or long double is unspecified.
Modify 26.2.1 to:
namespace std { template<class T> class complex; template<> class complex<float>; template<> class complex<double>; template<> class complex<long double>; template<class T> class imaginary; template<> class imaginary<float>; template<> class imaginary<double>; template<> class imaginary<long double>; // 26.2.6 operators: template<class T> complex<T> operator+(const complex<T>&, const complex<T>&); template<class T> complex<T> operator+(const complex<T>&, const T&); template<class T> complex<T> operator+(const T&, const complex<T>&); template<class T> imaginary<T> operator+( imaginary<T>, imaginary<T>); template<class T> complex<T> operator+(T, imaginary<T>); template<class T> complex<T> operator+(imaginary<T>, T); template<class T> complex<T> operator+(const complex<T>&, imaginary<T>); template<class T> complex<T> operator+(imaginary<T>, const complex<T>&); template<class T> complex<T> operator-(const complex<T>&, const complex<T>&); template<class T> complex<T> operator-(const complex<T>&, const T&); template<class T> complex<T> operator-(const T&, const complex<T>&); template<class T> imaginary<T> operator-(imaginary<T>, imaginary<T>); template<class T> complex<T> operator-(T, imaginary<T>); template<class T> complex<T> operator-(imaginary<T>, T); template<class T> complex<T> operator-(const complex<T>&, imaginary<T>); template<class T> complex<T> operator-(imaginary<T>, const complex<T>&); template<class T> complex<T> operator*(const complex<T>&, const complex<T>&); template<class T> complex<T> operator*(const complex<T>&, const T&); template<class T> complex<T> operator*(const T&, const complex<T>&); template<class T> T operator*(imaginary<T>, imaginary<T>); template<class T> imaginary<T> operator*(T, imaginary<T>); template<class T> imaginary<T> operator*(imaginary<T>, T); template<class T> complex<T> operator*(const complex<T>, imaginary<T>); template<class T> complex<T> operator*(imaginary<T>, complex<T>); template<class T> complex<T> operator/(const complex<T>&, const complex<T>&); template<class T> complex<T> operator/(const complex<T>&, const T&); template<class T> complex<T> operator/(const T&, const complex<T>&); template<class T> T operator/(imaginary<T>, imaginary<T>); template<class T> imaginary<T> operator/(T, imaginary<T>); template<class T> imaginary<T> operator/(imaginary<T>, T); template<class T> complex<T> operator/(const complex<T>&, imaginary<T>); template<class T> complex<T> operator/(imaginary<T>, const complex<T>&); template<class T> complex<T> operator+(const complex<T>&); template<class T> imaginary<T> operator+(imaginary<T>); template<class T> complex<T> operator-(const complex<T>&); template<class T> imaginary<T> operator-(imaginary<T>); template<class T> bool operator==(const complex<T>&, const complex<T>&); template<class T> bool operator==(const complex<T>&, const T&); template<class T> bool operator==(const T&, const complex<T>&); template<class T> bool operator==(imaginary<T>, imaginary<T>); template<class T> bool operator==(imaginary<T>, const complex<T>&); template<class T> bool operator==(const complex<T>&, imaginary<T>); template<class T> bool operator!=(const complex<T>&, const complex<T>&); template<class T> bool operator!=(const complex<T>&, const T&); template<class T> bool operator!=(const T&, const complex<T>&); template<class T> bool operator!=(imaginary<T>, imaginary<T>); template<class T> bool operator!=(imaginary<T>, const complex<T>&); template<class T> bool operator!=(const complex<T>&, imaginary<T>); template<class T> bool operator<(imaginary<T>, imaginary<T>); template<class T> bool operator<=(imaginary<T>, imaginary<T>); template<class T> bool operator>(imaginary<T>, imaginary<T>); template<class T> bool operator>=(imaginary<T>, imaginary<T>); template<class T, class charT, class traits> basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>&, complex<T>&); template<class T, class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>&, const complex<T>&);
Modify 26.2.1 to:
namespace std { template<class T> class complex { public: typedef T value_type; complex(const T& re = T(), const T& im = T()); template<class X> complex( imaginary<X> im ); template<class X> complex( X re, imaginary<X> im ); complex(const complex&); template<class X> complex(const complex<X>&); T real() const; T imag() const; complex<T>& operator= (const T&); complex<T>& operator+=(const T&); complex<T>& operator-=(const T&); complex<T>& operator*=(const T&); complex<T>& operator/=(const T&); template<class X> complex<T>& operator=(imaginary<X>); template<class X> complex<T>& operator+=(imaginary<X>); template<class X> complex<T>& operator-=(imaginary<X>); template<class X> complex<T>& operator*=(imaginary<X>); template<class X> complex<T>& operator/=(imaginary<X>); template<class X> complex<T>& operator=(const complex&); template<class X> complex<T>& operator= (const complex<X>&); template<class X> complex<T>& operator+=(const complex<X>&); template<class X> complex<T>& operator-=(const complex<X>&); template<class X> complex<T>& operator*=(const complex<X>&); template<class X> complex<T>& operator/=(const complex<X>&); }; }
Add a new section 26.2.3 [lib.imaginary]:
template<class T> class imaginary { T imag_; // exposition only public: typedef T value_type; imaginary( T imag = T() ); T& value(); T value() const; tempate<class X> imaginary<T>& operator+=( imaginary<X> r ); tempate<class X> imaginary<T>& operator-=( imaginary<X> r ); imaginary<T>& operator*=( T r ); imaginary<T>& operator/=( T r ); };
1 The class imaginary describes an imaginary number, that is, a complex number with zero real part.
Modify 26.2.1 to:
template<> class complex<float> { public: typedef float value_type; complex(float re = 0.0f, float im = 0.0f); template<class X> complex( imaginary<X> im ); template<class X> complex( X re, imaginary<X> im ); explicit complex(const complex<double>&); explicit complex(const complex<long double>&); float real() const; float imag() const; complex<float>& operator= (float); complex<float>& operator+=(float); complex<float>& operator-=(float); complex<float>& operator*=(float); complex<float>& operator/=(float); template<class X> complex<float>& operator=(imaginary<X>); template<class X> complex<float>& operator+=(imaginary<X>); template<class X> complex<float>& operator-=(imaginary<X>); template<class X> complex<float>& operator*=(imaginary<X>); template<class X> complex<float>& operator/=(imaginary<X>); complex<float>& operator=(const complex<float>&); template<class X> complex<float>& operator= (const complex<X>&); template<class X> complex<float>& operator+=(const complex<X>&); template<class X> complex<float>& operator-=(const complex<X>&); template<class X> complex<float>& operator*=(const complex<X>&); template<class X> complex<float>& operator/=(const complex<X>&); }; template<> class complex<double> { public: typedef double value_type; complex(double re = 0.0, double im = 0.0); template<class X> complex( imaginary<X> im ); template<class X> complex( X re, imaginary<X> im ); complex(const complex<float>&); explicit complex(const complex<long double>&); double real() const; double imag() const; complex<double>& operator= (double); complex<double>& operator+=(double); complex<double>& operator-=(double); complex<double>& operator*=(double); complex<double>& operator/=(double); template<class X> complex<double>& operator=(imaginary<X>); template<class X> complex<double>& operator+=(imaginary<X>); template<class X> complex<double>& operator-=(imaginary<X>); template<class X> complex<double>& operator*=(imaginary<X>); template<class X> complex<double>& operator/=(imaginary<X>); complex<double>& operator=(const complex<double>&); template<class X> complex<double>& operator= (const complex<X>&); template<class X> complex<double>& operator+=(const complex<X>&); template<class X> complex<double>& operator-=(const complex<X>&); template<class X> complex<double>& operator*=(const complex<X>&); template<class X> complex<double>& operator/=(const complex<X>&); }; template<> class complex<long double> { public: typedef long double value_type; complex(long double re = 0.0L, long double im = 0.0L); template<class X> complex( imaginary<X> im ); template<class X> complex( X re, imaginary<X> im ); complex(const complex<float>&); complex(const complex<double>&); long double real() const; long double imag() const; complex<long double>& operator=(const complex<long double>&); complex<long double>& operator= (long double); complex<long double>& operator+=(long double); complex<long double>& operator-=(long double); complex<long double>& operator*=(long double); complex<long double>& operator/=(long double); template<class X> complex<long double>& operator=(imaginary<X>); template<class X> complex<long double>& operator+=(imaginary<X>); template<class X> complex<long double>& operator-=(imaginary<X>); template<class X> complex<long double>& operator*=(imaginary<X>); template<class X> complex<long double>& operator/=(imaginary<X>); template<class X> complex<long double>& operator= (const complex<X>&); template<class X> complex<long double>& operator+=(const complex<X>&); template<class X> complex<long double>& operator-=(const complex<X>&); template<class X> complex<long double>& operator*=(const complex<X>&); template<class X> complex<long double>& operator/=(const complex<X>&); };
Add a new section 26.2.4 [lib.imaginary.special]:
template<> class imaginary<float> { public: typedef float value_type; imaginary( float imag = 0.0f ); float& value(); float value() const; tempate<class X> imaginary<float>& operator+=( imaginary<X> r ); tempate<class X> imaginary<float>& operator-=( imaginary<X> r ); imaginary<float>& operator*=( float r ); imaginary<float>& operator/=( float r ); }; template<> class imaginary<double> { public: typedef double value_type; imaginary( double imag = 0.0 ); double& value(); double value() const; tempate<class X> imaginary<double>& operator+=( imaginary<X> r ); tempate<class X> imaginary<double>& operator-=( imaginary<X> r ); imaginary<double>& operator*=( double r ); imaginary<double>& operator/=( double r ); }; template<> class imaginary<long double> { public: typedef long double value_type; imaginary( long double imag = 0.0L ); long double& value(); long double value() const; tempate<class X> imaginary<long double>& operator+=( imaginary<X> r ); tempate<class X> imaginary<long double>& operator-=( imaginary<X> r ); imaginary<long double>& operator*=( long double r ); imaginary<long double>& operator/=( long double r ); };
Add the following to 26.2.4:
template<class X> complex( imaginary<T> im );
3 Effects: Constructs an object of class complex.
4 Postcondition: real() == 0 && imag() == im.value().
template<class X> complex( X re, imaginary<T> im );
5 Effects: Constructs an object of class complex.
6 Postcondition: real() == re && imag() == im.value().
Add the following to 26.2.5:
template<class X> complex<T>& operator=(imaginary<X> im);
Postcondition: real() == 0 && imag() == im.value().
Returns: *this.
template<class X> complex<T>& operator+=(imaginary<X> im);
Effects: Adds im.value() to the imaginary part of *this.
Returns: *this.
template<class X> complex<T>& operator-=(imaginary<X> im);
Effects: Subtracts im.value() from the imaginary part of *this.
Returns: *this.
template<class X> complex<T>& operator*=(imaginary<X> im);
Effects: Multiplies the imaginary number im with *this and stores the product in *this.
Complexity: Faster than multiplying two complex numbers.
Returns: *this.
template<class X> complex<T>& operator/=(imaginary<X> im);
Effects: Divides *this with the imaginary number im and stores the product in *this.
Complexity: Faster than dividing two complex numbers.
Returns: *this.
Add a new section 26.2.6 [lib.imaginary.members]:
imaginary( T imag = T() );
1 Effects: Constructs an object of class imaginary.
2 Postcondition: value() == imag.
Add a new section 26.2.7 [lib.imaginary.members.ops]:
T& value();
3 Returns: imag_
T value() const;
4 Returns: imag_
tempate<class X> imaginary<T>& operator+=( imaginary<X> r );
5 Effects: imag_ += r.value().
6 returns: *this.
tempate<class X> imaginary<T>& operator-=( imaginary<X> r );
7 Effects: imag_ -= r.value().
8 Returns: *this.
imaginary<T>& operator*=( T r );
9 Effects: imag_ *= r.
10 Returns: *this.
Modify 26.2.3 to:
template<class T> complex<T> operator+(const complex<T>& lhs, const complex<T>& rhs); template<class T> complex<T> operator+(const complex<T>& lhs, const T& rhs); template<class T> complex<T> operator+(const T& lhs, const complex<T>& rhs); template<class T> complex<T> operator+( T lhs, imaginary<T> rhs ); template<class T> complex<T> operator+( imaginary<T> lhs, T rhs ); template<class T> complex<T> operator+( const complex<T>& lhs, imaginary<T> rhs ); template<class T> complex<T> operator+( imaginary<T> lhs, const complex<T>& rhs );
Modify 26.2.6 to:
template<class T> complex<T> operator-(const complex<T>& lhs, const complex<T>& rhs); template<class T> complex<T> operator-(const complex<T>& lhs, const T& rhs); template<class T> complex<T> operator-(const T& lhs, const complex<T>& rhs); template<class T> complex<T> operator-( T lhs, imaginary<T> rhs ); template<class T> complex<T> operator-( imaginary<T> lhs, T rhs ); template<class T> complex<T> operator-( const complex<T>& lhs, imaginary<T> rhs ); template<class T> complex<T> operator-( imaginary<T> lhs, const complex<T>& rhs );
Modify 26.2.7 to:
template<class T> complex<T> operator*(const complex<T>& lhs, const complex<T>& rhs); template<class T> complex<T> operator*(const complex<T>& lhs, const T& rhs); template<class T> complex<T> operator*(const T& lhs, const complex<T>& rhs); template<class T> complex<T> operator*( const complex<T>& lhs, imaginary<T> rhs ); template<class T> complex<T> operator*( imaginary<T> lhs, const complex<T>& rhs );
Modify 26.2.8 to:
template<class T> complex<T> operator/(const complex<T>& lhs, const complex<T>& rhs); template<class T> complex<T> operator/(const complex<T>& lhs, const T& rhs); template<class T> complex<T> operator/(const T& lhs, const complex<T>& rhs); template<class T> complex<T> operator/( const complex<T>& lhs, imaginary<T> rhs ); template<class T> complex<T> operator/( imaginary<T> lhs, const complex<T>& rhs );
Modify 26.2.9 to:
template<class T> bool operator==(const complex<T>& lhs, const complex<T>& rhs); template<class T> bool operator==(const complex<T>& lhs, const T& rhs); template<class T> bool operator==(const T& lhs, const complex<T>& rhs); template<class T> complex<T> operator==( const complex<T>& lhs, imaginary<T> rhs ); template<class T> complex<T> operator==( imaginary<T> lhs, const complex<T>& rhs );
Returns: lhs.real() == rhs.real() && lhs.imag() == rhs.imag().
Notes: The imaginary part is assumed to be T(), or 0.0, for the T arguments. The real part is assumed to be 0.0 for imaginary<T> arguments.
Modify 26.2.10 to:
template<class T> bool operator!=(const complex<T>& lhs, const complex<T>& rhs); template<class T> bool operator!=(const complex<T>& lhs, const T& rhs); template<class T> bool operator!=(const T& lhs, const complex<T>& rhs); template<class T> complex<T> operator!=( const complex<T>& lhs, imaginary<T> rhs ); template<class T> complex<T> operator!=( imaginary<T> lhs, const complex<T>& rhs );
Returns: lhs.real() != rhs.real() || lhs.imag() != rhs.imag().
Notes: The imaginary part is assumed to be T(), or 0.0, for the T arguments. The real part is assumed to be 0.0 for imaginary<T> arguments.
Add a new section 26.2.7 [lib.imaginary.ops]
template<class T> imaginary<T> operator+( imaginary<T> lhs, imaginary<T> rhs );
1 Returns: lhs += rhs.
template<class T> imaginary<T> operator-( imaginary<T> lhs, imaginary<T> rhs );
2 Returns: lhs -= rhs.
template<class T> T operator*( imaginary<T> lhs, imaginary<T> rhs );
3 Returns: - lhs.value() * rhs.value().
template<class T> imaginary<T> operator*( T lhs, imaginary<T> rhs );
4 Returns: rhs *= lhs.
template<class T> imaginary<T> operator*( imaginary<T> lhs, T rhs );
5 Returns: lhs *= rhs.
template<class T> T operator/(imaginary<T> lhs, imaginary<T> rhs);
6 Returns: lhs.value()/rhs.value().
template<class T> imaginary<T> operator/(T lhs, imaginary<T> rhs);
7 Returns: imaginary<T>( lhs/rhs.value() ).
template<class T> imaginary<T> operator/(imaginary<T> lhs, T rhs);
8 Returns: lhs /= rhs.
template<class T> imaginary<T> operator+( imaginary<T> rhs );
9 Notes: unary operator.
10 Returns: rhs;
template<class T> imaginary<T> operator-( imaginary<T> rhs );
11 Notes: unary operator.
12 Returns: rhs *= -1..
template<class T> bool operator==(imaginary<T> lhs, imaginary<T> rhs);
13 Returns: lhs.value() == rhs.value().
template<class T> bool operator!=(imaginary<T> lhs, imaginary<T> rhs);
14 Returns: lhs.value() != rhs.value().
template<class T> bool operator<(imaginary<T> lhs, imaginary<T> rhs);
15 Returns: lhs.value() < rhs.value().
template<class T> bool operator<=(imaginary<T> lhs, imaginary<T> rhs);
16 Returns: lhs.value() <= rhs.value().
template<class T> bool operator>(imaginary<T> lhs, imaginary<T> rhs);
17 Returns: lhs.value() > rhs.value().
template<class T> bool operator>=(imaginary<T> lhs, imaginary<T> rhs);
18 Returns: lhs.value() >= rhs.value().
The author would like to thank Bill Plauger.