/*  Copyright (C) 2015  Povilas Kanapickas <povilas@radix.lt>

    This file is part of cppreference-doc

    This work is licensed under the Creative Commons Attribution-ShareAlike 3.0
    Unported License. To view a copy of this license, visit
    http://creativecommons.org/licenses/by-sa/3.0/ or send a letter to Creative
    Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA.

    Permission is granted to copy, distribute and/or modify this document
    under the terms of the GNU Free Documentation License, Version 1.3 or
    any later version published by the Free Software Foundation; with no
    Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
*/

#ifndef CPPREFERENCE_COMPLEX_H
#define CPPREFERENCE_COMPLEX_H

namespace std {

template<class T>
class complex {
public:
    typedef T value_type;

    complex(const T& re = T(), const T& im = T());

    complex(const complex& other);

    template<class X>
    complex(const complex<X>& other);

    complex<T>& operator=(const T& x);

    template<class X>
    complex<T>& operator=(const complex<X>& cx);

    T real() const;
    void real(T value);

    T imag() const;
    void imag(T value);

    complex<T>& operator+=(const T& other);

    template<class X>
    complex<T>& operator+=(const complex<X>& other);

    complex<T>& operator-=(const T& other);

    template<class X>
    complex<T>& operator-=(const complex<X>& other);

    complex<T>& operator*=(const T& other);

    template<class X>
    complex<T>& operator*=(const complex<X>& other);

    complex<T>& operator/=(const T& other);

    template<class X>
    complex<T>& operator/=(const complex<X>& other);

    template<class T>
    complex<T> operator+(const complex<T>& val);

    template<class T>
    complex<T> operator-(const complex<T>& val);
};

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, 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, 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, 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>
bool operator==(const complex<T>& lhs, const complex<T>& rhs);
template<class T>
bool operator!=(const complex<T>& lhs, const complex<T>& rhs);
template<class T>
bool operator<(const complex<T>& lhs, const complex<T>& rhs);
template<class T>
bool operator<=(const complex<T>& lhs, const complex<T>& rhs);
template<class T>
bool operator>(const complex<T>& lhs, const complex<T>& rhs);
template<class T>
bool operator>=(const complex<T>& lhs, const complex<T>& rhs);

template <class T, class CharT, class Traits>
std::basic_ostream<CharT, Traits>&
operator<<(std::basic_ostream<CharT, Traits>& os,
           const std::complex<T>& x);

template <class T, class CharT, class Traits>
std::basic_istream<CharT, Traits>&
operator>>(std::basic_istream<CharT, Traits>& is,
           std::complex<T>& x);

template<class T>
T real(const complex<T>& z);

template<class T>
T imag(const complex<T>& z);

template<class T>
T abs(const complex<T>& z);
template<class T>
T arg(const complex<T>& z);
template<class T>
T norm(const complex<T>& z);
template<class T>
complex<T> conj(const complex<T>& z);
template<class T>
complex<T> proj(const complex<T>& z);
template<class T>
complex<T> polar(const T& r, const T& theta = 0);
template<class T>
complex<T> exp(const complex<T>& z);
template<class T>
complex<T> log(const complex<T>& z);
template<class T>
complex<T> log10(const complex<T>& z);

template<class T>
complex<T> pow(const complex<T>& x, const complex<T>& y);
template<class T>
complex<T> pow(const complex<T>& x, const T& y);
template<class T>
complex<T> pow(const T& x, const complex<T>& y);
template<class T>
complex<T> sqrt(const complex<T>& z);

template<class T>
complex<T> sin(const complex<T>& z);
template<class T>
complex<T> cos(const complex<T>& z);
template<class T>
complex<T> tan(const complex<T>& z);

template<class T>
complex<T> sinh(const complex<T>& z);
template<class T>
complex<T> cosh(const complex<T>& z);
template<class T>
complex<T> tanh(const complex<T>& z);
#if CPPREFERENCE_STDVER>= 2011
template<class T>
complex<T> asin(const complex<T>& z);
template<class T>
complex<T> acos(const complex<T>& z);
template<class T>
complex<T> atan(const complex<T>& z);

template<class T>
complex<T> asinh(const complex<T>& z);
template<class T>
complex<T> acosh(const complex<T>& z);
template<class T>
complex<T> atanh(const complex<T>& z);

#endif // CPPREFERENCE_STDVER>= 2011

} // namespace std

#endif // CPPREFERENCE_COMPLEX_H
