| 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.