chromium/third_party/libc++/src/include/complex

// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef _LIBCPP_COMPLEX
#define _LIBCPP_COMPLEX

/*
    complex synopsis

namespace std
{

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

    complex(const T& re = T(), const T& im = T()); // constexpr in C++14
    complex(const complex&);  // constexpr in C++14
    template<class X> complex(const complex<X>&);  // constexpr in C++14

    T real() const; // constexpr in C++14
    T imag() const; // constexpr in C++14

    void real(T); // constexpr in C++20
    void imag(T); // constexpr in C++20

    complex<T>& operator= (const T&); // constexpr in C++20
    complex<T>& operator+=(const T&); // constexpr in C++20
    complex<T>& operator-=(const T&); // constexpr in C++20
    complex<T>& operator*=(const T&); // constexpr in C++20
    complex<T>& operator/=(const T&); // constexpr in C++20

    complex& operator=(const complex&); // constexpr in C++20
    template<class X> complex<T>& operator= (const complex<X>&); // constexpr in C++20
    template<class X> complex<T>& operator+=(const complex<X>&); // constexpr in C++20
    template<class X> complex<T>& operator-=(const complex<X>&); // constexpr in C++20
    template<class X> complex<T>& operator*=(const complex<X>&); // constexpr in C++20
    template<class X> complex<T>& operator/=(const complex<X>&); // constexpr in C++20
};

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

    constexpr complex(float re = 0.0f, float im = 0.0f);
    explicit constexpr complex(const complex<double>&);
    explicit constexpr complex(const complex<long double>&);

    constexpr float real() const;
    void real(float); // constexpr in C++20
    constexpr float imag() const;
    void imag(float); // constexpr in C++20

    complex<float>& operator= (float); // constexpr in C++20
    complex<float>& operator+=(float); // constexpr in C++20
    complex<float>& operator-=(float); // constexpr in C++20
    complex<float>& operator*=(float); // constexpr in C++20
    complex<float>& operator/=(float); // constexpr in C++20

    complex<float>& operator=(const complex<float>&); // constexpr in C++20
    template<class X> complex<float>& operator= (const complex<X>&); // constexpr in C++20
    template<class X> complex<float>& operator+=(const complex<X>&); // constexpr in C++20
    template<class X> complex<float>& operator-=(const complex<X>&); // constexpr in C++20
    template<class X> complex<float>& operator*=(const complex<X>&); // constexpr in C++20
    template<class X> complex<float>& operator/=(const complex<X>&); // constexpr in C++20
};

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

    constexpr complex(double re = 0.0, double im = 0.0);
    constexpr complex(const complex<float>&);
    explicit constexpr complex(const complex<long double>&);

    constexpr double real() const;
    void real(double); // constexpr in C++20
    constexpr double imag() const;
    void imag(double); // constexpr in C++20

    complex<double>& operator= (double); // constexpr in C++20
    complex<double>& operator+=(double); // constexpr in C++20
    complex<double>& operator-=(double); // constexpr in C++20
    complex<double>& operator*=(double); // constexpr in C++20
    complex<double>& operator/=(double); // constexpr in C++20
    complex<double>& operator=(const complex<double>&); // constexpr in C++20

    template<class X> complex<double>& operator= (const complex<X>&); // constexpr in C++20
    template<class X> complex<double>& operator+=(const complex<X>&); // constexpr in C++20
    template<class X> complex<double>& operator-=(const complex<X>&); // constexpr in C++20
    template<class X> complex<double>& operator*=(const complex<X>&); // constexpr in C++20
    template<class X> complex<double>& operator/=(const complex<X>&); // constexpr in C++20
};

template<>
class complex<long double>
{
public:
    typedef long double value_type;

    constexpr complex(long double re = 0.0L, long double im = 0.0L);
    constexpr complex(const complex<float>&);
    constexpr complex(const complex<double>&);

    constexpr long double real() const;
    void real(long double); // constexpr in C++20
    constexpr long double imag() const;
    void imag(long double); // constexpr in C++20

    complex<long double>& operator=(const complex<long double>&); // constexpr in C++20
    complex<long double>& operator= (long double); // constexpr in C++20
    complex<long double>& operator+=(long double); // constexpr in C++20
    complex<long double>& operator-=(long double); // constexpr in C++20
    complex<long double>& operator*=(long double); // constexpr in C++20
    complex<long double>& operator/=(long double); // constexpr in C++20

    template<class X> complex<long double>& operator= (const complex<X>&); // constexpr in C++20
    template<class X> complex<long double>& operator+=(const complex<X>&); // constexpr in C++20
    template<class X> complex<long double>& operator-=(const complex<X>&); // constexpr in C++20
    template<class X> complex<long double>& operator*=(const complex<X>&); // constexpr in C++20
    template<class X> complex<long double>& operator/=(const complex<X>&); // constexpr in C++20
};

// 26.3.6 operators:
template<class T> complex<T> operator+(const complex<T>&, const complex<T>&); // constexpr in C++20
template<class T> complex<T> operator+(const complex<T>&, const T&);          // constexpr in C++20
template<class T> complex<T> operator+(const T&, const complex<T>&);          // constexpr in C++20
template<class T> complex<T> operator-(const complex<T>&, const complex<T>&); // constexpr in C++20
template<class T> complex<T> operator-(const complex<T>&, const T&);          // constexpr in C++20
template<class T> complex<T> operator-(const T&, const complex<T>&);          // constexpr in C++20
template<class T> complex<T> operator*(const complex<T>&, const complex<T>&); // constexpr in C++20
template<class T> complex<T> operator*(const complex<T>&, const T&);          // constexpr in C++20
template<class T> complex<T> operator*(const T&, const complex<T>&);          // constexpr in C++20
template<class T> complex<T> operator/(const complex<T>&, const complex<T>&); // constexpr in C++20
template<class T> complex<T> operator/(const complex<T>&, const T&);          // constexpr in C++20
template<class T> complex<T> operator/(const T&, const complex<T>&);          // constexpr in C++20
template<class T> complex<T> operator+(const complex<T>&);                    // constexpr in C++20
template<class T> complex<T> operator-(const complex<T>&);                    // constexpr in C++20
template<class T> bool operator==(const complex<T>&, const complex<T>&);      // constexpr in C++14
template<class T> bool operator==(const complex<T>&, const T&);               // constexpr in C++14
template<class T> bool operator==(const T&, const complex<T>&);               // constexpr in C++14, removed in C++20
template<class T> bool operator!=(const complex<T>&, const complex<T>&);      // constexpr in C++14, removed in C++20
template<class T> bool operator!=(const complex<T>&, const T&);               // constexpr in C++14, removed in C++20
template<class T> bool operator!=(const T&, const complex<T>&);               // constexpr in C++14, removed in C++20

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>&);

// 26.3.7 values:

template<class T>              T real(const complex<T>&); // constexpr in C++14
                     long double real(long double);       // constexpr in C++14
                          double real(double);            // constexpr in C++14
template<Integral T>      double real(T);                 // constexpr in C++14
                          float  real(float);             // constexpr in C++14

template<class T>              T imag(const complex<T>&); // constexpr in C++14
                     long double imag(long double);       // constexpr in C++14
                          double imag(double);            // constexpr in C++14
template<Integral T>      double imag(T);                 // constexpr in C++14
                          float  imag(float);             // constexpr in C++14

template<class T> T abs(const complex<T>&);

template<class T>              T arg(const complex<T>&);
                     long double arg(long double);
                          double arg(double);
template<Integral T>      double arg(T);
                          float  arg(float);

template<class T>              T norm(const complex<T>&); // constexpr in C++20
                     long double norm(long double);       // constexpr in C++20
                          double norm(double);            // constexpr in C++20
template<Integral T>      double norm(T);                 // constexpr in C++20
                          float  norm(float);             // constexpr in C++20

template<class T>      complex<T>           conj(const complex<T>&); // constexpr in C++20
                       complex<long double> conj(long double);       // constexpr in C++20
                       complex<double>      conj(double);            // constexpr in C++20
template<Integral T>   complex<double>      conj(T);                 // constexpr in C++20
                       complex<float>       conj(float);             // constexpr in C++20

template<class T>    complex<T>           proj(const complex<T>&);
                     complex<long double> proj(long double);
                     complex<double>      proj(double);
template<Integral T> complex<double>      proj(T);
                     complex<float>       proj(float);

template<class T> complex<T> polar(const T&, const T& = T());

// 26.3.8 transcendentals:
template<class T> complex<T> acos(const complex<T>&);
template<class T> complex<T> asin(const complex<T>&);
template<class T> complex<T> atan(const complex<T>&);
template<class T> complex<T> acosh(const complex<T>&);
template<class T> complex<T> asinh(const complex<T>&);
template<class T> complex<T> atanh(const complex<T>&);
template<class T> complex<T> cos (const complex<T>&);
template<class T> complex<T> cosh (const complex<T>&);
template<class T> complex<T> exp (const complex<T>&);
template<class T> complex<T> log (const complex<T>&);
template<class T> complex<T> log10(const complex<T>&);

template<class T> complex<T> pow(const complex<T>&, const T&);
template<class T> complex<T> pow(const complex<T>&, const complex<T>&);
template<class T> complex<T> pow(const T&, const complex<T>&);

template<class T> complex<T> sin (const complex<T>&);
template<class T> complex<T> sinh (const complex<T>&);
template<class T> complex<T> sqrt (const complex<T>&);
template<class T> complex<T> tan (const complex<T>&);
template<class T> complex<T> tanh (const complex<T>&);

  // [complex.tuple], tuple interface
  template<class T> struct tuple_size;                               // Since C++26
  template<size_t I, class T> struct tuple_element;                  // Since C++26
  template<class T> struct tuple_size<complex<T>>;                   // Since C++26
  template<size_t I, class T> struct tuple_element<I, complex<T>>;   // Since C++26
  template<size_t I, class T>
    constexpr T& get(complex<T>&) noexcept;                          // Since C++26
  template<size_t I, class T>
    constexpr T&& get(complex<T>&&) noexcept;                        // Since C++26
  template<size_t I, class T>
    constexpr const T& get(const complex<T>&) noexcept;              // Since C++26
  template<size_t I, class T>
    constexpr const T&& get(const complex<T>&&) noexcept;            // Since C++26

  // [complex.literals], complex literals
  inline namespace literals {
  inline namespace complex_literals {
    constexpr complex<long double> operator""il(long double);        // Since C++14
    constexpr complex<long double> operator""il(unsigned long long); // Since C++14
    constexpr complex<double> operator""i(long double);              // Since C++14
    constexpr complex<double> operator""i(unsigned long long);       // Since C++14
    constexpr complex<float> operator""if(long double);              // Since C++14
    constexpr complex<float> operator""if(unsigned long long);       // Since C++14
  }
  }
}  // std

*/

#include <__config>
#include <__fwd/complex.h>
#include <__fwd/tuple.h>
#include <__tuple/tuple_element.h>
#include <__tuple/tuple_size.h>
#include <__type_traits/conditional.h>
#include <__utility/move.h>
#include <cmath>
#include <version>

#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
#  include <sstream> // for std::basic_ostringstream
#endif

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
#  pragma GCC system_header
#endif

_LIBCPP_PUSH_MACROS
#include <__undef_macros>

_LIBCPP_BEGIN_NAMESPACE_STD

template <class _Tp>
class _LIBCPP_TEMPLATE_VIS complex;

template <class _Tp, __enable_if_t<is_floating_point<_Tp>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
operator*(const complex<_Tp>& __z, const complex<_Tp>& __w);

template <class _Tp, __enable_if_t<!is_floating_point<_Tp>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
operator*(const complex<_Tp>& __z, const complex<_Tp>& __w);

template <class _Tp, __enable_if_t<is_floating_point<_Tp>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
operator/(const complex<_Tp>& __x, const complex<_Tp>& __y);

template <class _Tp, __enable_if_t<!is_floating_point<_Tp>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
operator/(const complex<_Tp>& __x, const complex<_Tp>& __y);

template <class _Tp>
class _LIBCPP_TEMPLATE_VIS complex {};

template <>
class _LIBCPP_TEMPLATE_VIS complex<double>;
template <>
class _LIBCPP_TEMPLATE_VIS complex<long double>;

struct __from_builtin_tag {};

__complex_t;

template <class _Tp>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __complex_t<_Tp> __make_complex(_Tp __re, _Tp __im) {}

template <>
class _LIBCPP_TEMPLATE_VIS complex<float> {};

template <>
class _LIBCPP_TEMPLATE_VIS complex<double> {};

template <>
class _LIBCPP_TEMPLATE_VIS complex<long double> {};

inline _LIBCPP_CONSTEXPR complex<float>::complex(const complex<double>& __c) :{}

inline _LIBCPP_CONSTEXPR complex<float>::complex(const complex<long double>& __c)
    :{}

inline _LIBCPP_CONSTEXPR complex<double>::complex(const complex<float>& __c) :{}

inline _LIBCPP_CONSTEXPR complex<double>::complex(const complex<long double>& __c)
    :{}

inline _LIBCPP_CONSTEXPR complex<long double>::complex(const complex<float>& __c)
    :{}

inline _LIBCPP_CONSTEXPR complex<long double>::complex(const complex<double>& __c)
    :{}

// 26.3.6 operators:

template <class _Tp>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
operator+(const complex<_Tp>& __x, const complex<_Tp>& __y) {}

template <class _Tp>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
operator+(const complex<_Tp>& __x, const _Tp& __y) {}

template <class _Tp>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
operator+(const _Tp& __x, const complex<_Tp>& __y) {}

template <class _Tp>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
operator-(const complex<_Tp>& __x, const complex<_Tp>& __y) {}

template <class _Tp>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
operator-(const complex<_Tp>& __x, const _Tp& __y) {}

template <class _Tp>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
operator-(const _Tp& __x, const complex<_Tp>& __y) {}

template <class _Tp, __enable_if_t<is_floating_point<_Tp>::value, int> >
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
operator*(const complex<_Tp>& __lhs, const complex<_Tp>& __rhs) {}

template <class _Tp, __enable_if_t<!is_floating_point<_Tp>::value, int> >
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
operator*(const complex<_Tp>& __z, const complex<_Tp>& __w) {}

template <class _Tp>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
operator*(const complex<_Tp>& __x, const _Tp& __y) {}

template <class _Tp>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
operator*(const _Tp& __x, const complex<_Tp>& __y) {}

template <class _Tp, __enable_if_t<is_floating_point<_Tp>::value, int> >
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
operator/(const complex<_Tp>& __lhs, const complex<_Tp>& __rhs) {}

template <class _Tp, __enable_if_t<!is_floating_point<_Tp>::value, int> >
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
operator/(const complex<_Tp>& __z, const complex<_Tp>& __w) {}

template <class _Tp>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
operator/(const complex<_Tp>& __x, const _Tp& __y) {}

template <class _Tp>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
operator/(const _Tp& __x, const complex<_Tp>& __y) {}

template <class _Tp>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> operator+(const complex<_Tp>& __x) {}

template <class _Tp>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> operator-(const complex<_Tp>& __x) {}

template <class _Tp>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool
operator==(const complex<_Tp>& __x, const complex<_Tp>& __y) {}

template <class _Tp>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool operator==(const complex<_Tp>& __x, const _Tp& __y) {}

#if _LIBCPP_STD_VER <= 17

template <class _Tp>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool operator==(const _Tp& __x, const complex<_Tp>& __y) {
  return __x == __y.real() && 0 == __y.imag();
}

template <class _Tp>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool
operator!=(const complex<_Tp>& __x, const complex<_Tp>& __y) {
  return !(__x == __y);
}

template <class _Tp>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool operator!=(const complex<_Tp>& __x, const _Tp& __y) {
  return !(__x == __y);
}

template <class _Tp>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool operator!=(const _Tp& __x, const complex<_Tp>& __y) {
  return !(__x == __y);
}

#endif

// 26.3.7 values:

template <class _Tp, bool = is_integral<_Tp>::value, bool = is_floating_point<_Tp>::value >
struct __libcpp_complex_overload_traits {};

// Integral Types
__libcpp_complex_overload_traits<_Tp, true, false>;

// Floating point types
__libcpp_complex_overload_traits<_Tp, false, true>;

// real

template <class _Tp>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp real(const complex<_Tp>& __c) {}

template <class _Tp>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 typename __libcpp_complex_overload_traits<_Tp>::_ValueType
real(_Tp __re) {}

// imag

template <class _Tp>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp imag(const complex<_Tp>& __c) {}

template <class _Tp>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 typename __libcpp_complex_overload_traits<_Tp>::_ValueType
imag(_Tp) {}

// abs

template <class _Tp>
inline _LIBCPP_HIDE_FROM_ABI _Tp abs(const complex<_Tp>& __c) {}

// arg

template <class _Tp>
inline _LIBCPP_HIDE_FROM_ABI _Tp arg(const complex<_Tp>& __c) {}

template <class _Tp, __enable_if_t<is_same<_Tp, long double>::value, int> = 0>
inline _LIBCPP_HIDE_FROM_ABI long double arg(_Tp __re) {}

template <class _Tp, __enable_if_t<is_integral<_Tp>::value || is_same<_Tp, double>::value, int> = 0>
inline _LIBCPP_HIDE_FROM_ABI double arg(_Tp __re) {}

template <class _Tp, __enable_if_t<is_same<_Tp, float>::value, int> = 0>
inline _LIBCPP_HIDE_FROM_ABI float arg(_Tp __re) {}

// norm

template <class _Tp>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp norm(const complex<_Tp>& __c) {}

template <class _Tp>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 typename __libcpp_complex_overload_traits<_Tp>::_ValueType
norm(_Tp __re) {}

// conj

template <class _Tp>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> conj(const complex<_Tp>& __c) {}

template <class _Tp>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 typename __libcpp_complex_overload_traits<_Tp>::_ComplexType
conj(_Tp __re) {}

// proj

template <class _Tp>
inline _LIBCPP_HIDE_FROM_ABI complex<_Tp> proj(const complex<_Tp>& __c) {}

template <class _Tp, __enable_if_t<is_floating_point<_Tp>::value, int> = 0>
inline _LIBCPP_HIDE_FROM_ABI typename __libcpp_complex_overload_traits<_Tp>::_ComplexType proj(_Tp __re) {}

template <class _Tp, __enable_if_t<is_integral<_Tp>::value, int> = 0>
inline _LIBCPP_HIDE_FROM_ABI typename __libcpp_complex_overload_traits<_Tp>::_ComplexType proj(_Tp __re) {}

// polar

template <class _Tp>
_LIBCPP_HIDE_FROM_ABI complex<_Tp> polar(const _Tp& __rho, const _Tp& __theta = _Tp()) {}

// log

template <class _Tp>
inline _LIBCPP_HIDE_FROM_ABI complex<_Tp> log(const complex<_Tp>& __x) {}

// log10

template <class _Tp>
inline _LIBCPP_HIDE_FROM_ABI complex<_Tp> log10(const complex<_Tp>& __x) {}

// sqrt

template <class _Tp>
_LIBCPP_HIDE_FROM_ABI complex<_Tp> sqrt(const complex<_Tp>& __x) {}

// exp

template <class _Tp>
_LIBCPP_HIDE_FROM_ABI complex<_Tp> exp(const complex<_Tp>& __x) {}

// pow

template <class _Tp>
inline _LIBCPP_HIDE_FROM_ABI complex<_Tp> pow(const complex<_Tp>& __x, const complex<_Tp>& __y) {}

template <class _Tp, class _Up>
inline _LIBCPP_HIDE_FROM_ABI complex<typename __promote<_Tp, _Up>::type>
pow(const complex<_Tp>& __x, const complex<_Up>& __y) {}

template <class _Tp, class _Up, __enable_if_t<is_arithmetic<_Up>::value, int> = 0>
inline _LIBCPP_HIDE_FROM_ABI complex<typename __promote<_Tp, _Up>::type> pow(const complex<_Tp>& __x, const _Up& __y) {}

template <class _Tp, class _Up, __enable_if_t<is_arithmetic<_Tp>::value, int> = 0>
inline _LIBCPP_HIDE_FROM_ABI complex<typename __promote<_Tp, _Up>::type> pow(const _Tp& __x, const complex<_Up>& __y) {}

// __sqr, computes pow(x, 2)

template <class _Tp>
inline _LIBCPP_HIDE_FROM_ABI complex<_Tp> __sqr(const complex<_Tp>& __x) {}

// asinh

template <class _Tp>
_LIBCPP_HIDE_FROM_ABI complex<_Tp> asinh(const complex<_Tp>& __x) {}

// acosh

template <class _Tp>
_LIBCPP_HIDE_FROM_ABI complex<_Tp> acosh(const complex<_Tp>& __x) {}

// atanh

template <class _Tp>
_LIBCPP_HIDE_FROM_ABI complex<_Tp> atanh(const complex<_Tp>& __x) {}

// sinh

template <class _Tp>
_LIBCPP_HIDE_FROM_ABI complex<_Tp> sinh(const complex<_Tp>& __x) {}

// cosh

template <class _Tp>
_LIBCPP_HIDE_FROM_ABI complex<_Tp> cosh(const complex<_Tp>& __x) {}

// tanh

template <class _Tp>
_LIBCPP_HIDE_FROM_ABI complex<_Tp> tanh(const complex<_Tp>& __x) {}

// asin

template <class _Tp>
_LIBCPP_HIDE_FROM_ABI complex<_Tp> asin(const complex<_Tp>& __x) {}

// acos

template <class _Tp>
_LIBCPP_HIDE_FROM_ABI complex<_Tp> acos(const complex<_Tp>& __x) {}

// atan

template <class _Tp>
_LIBCPP_HIDE_FROM_ABI complex<_Tp> atan(const complex<_Tp>& __x) {}

// sin

template <class _Tp>
_LIBCPP_HIDE_FROM_ABI complex<_Tp> sin(const complex<_Tp>& __x) {}

// cos

template <class _Tp>
inline _LIBCPP_HIDE_FROM_ABI complex<_Tp> cos(const complex<_Tp>& __x) {}

// tan

template <class _Tp>
_LIBCPP_HIDE_FROM_ABI complex<_Tp> tan(const complex<_Tp>& __x) {}

#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
template <class _Tp, class _CharT, class _Traits>
_LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>&
operator>>(basic_istream<_CharT, _Traits>& __is, complex<_Tp>& __x) {}

template <class _Tp, class _CharT, class _Traits>
_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>&
operator<<(basic_ostream<_CharT, _Traits>& __os, const complex<_Tp>& __x) {}
#endif // !_LIBCPP_HAS_NO_LOCALIZATION

#if _LIBCPP_STD_VER >= 26

// [complex.tuple], tuple interface

template <class _Tp>
struct tuple_size<complex<_Tp>> : integral_constant<size_t, 2> {};

template <size_t _Ip, class _Tp>
struct tuple_element<_Ip, complex<_Tp>> {
  static_assert(_Ip < 2, "Index value is out of range.");
  using type = _Tp;
};

template <size_t _Ip, class _Xp>
_LIBCPP_HIDE_FROM_ABI constexpr _Xp& get(complex<_Xp>& __z) noexcept {
  static_assert(_Ip < 2, "Index value is out of range.");
  if constexpr (_Ip == 0) {
    return __z.__re_;
  } else {
    return __z.__im_;
  }
}

template <size_t _Ip, class _Xp>
_LIBCPP_HIDE_FROM_ABI constexpr _Xp&& get(complex<_Xp>&& __z) noexcept {
  static_assert(_Ip < 2, "Index value is out of range.");
  if constexpr (_Ip == 0) {
    return std::move(__z.__re_);
  } else {
    return std::move(__z.__im_);
  }
}

template <size_t _Ip, class _Xp>
_LIBCPP_HIDE_FROM_ABI constexpr const _Xp& get(const complex<_Xp>& __z) noexcept {
  static_assert(_Ip < 2, "Index value is out of range.");
  if constexpr (_Ip == 0) {
    return __z.__re_;
  } else {
    return __z.__im_;
  }
}

template <size_t _Ip, class _Xp>
_LIBCPP_HIDE_FROM_ABI constexpr const _Xp&& get(const complex<_Xp>&& __z) noexcept {
  static_assert(_Ip < 2, "Index value is out of range.");
  if constexpr (_Ip == 0) {
    return std::move(__z.__re_);
  } else {
    return std::move(__z.__im_);
  }
}

#endif // _LIBCPP_STD_VER >= 26

#if _LIBCPP_STD_VER >= 14
// Literal suffix for complex number literals [complex.literals]
inline namespace literals {
inline namespace complex_literals {
_LIBCPP_HIDE_FROM_ABI inline constexpr complex<long double> operator""il(long double __im) {}

_LIBCPP_HIDE_FROM_ABI inline constexpr complex<long double> operator""il(unsigned long long __im) {}

_LIBCPP_HIDE_FROM_ABI inline constexpr complex<double> operator""i(long double __im) {}

_LIBCPP_HIDE_FROM_ABI inline constexpr complex<double> operator""i(unsigned long long __im) {}

_LIBCPP_HIDE_FROM_ABI inline constexpr complex<float> operator""if(long double __im) {}

_LIBCPP_HIDE_FROM_ABI inline constexpr complex<float> operator""if(unsigned long long __im) {}
} // namespace complex_literals
} // namespace literals
#endif

_LIBCPP_END_NAMESPACE_STD

_LIBCPP_POP_MACROS

#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
#  include <iosfwd>
#  include <stdexcept>
#  include <type_traits>
#endif

#endif // _LIBCPP_COMPLEX