xref: /freebsd/contrib/llvm-project/libcxx/include/complex (revision cb14a3fe5122c879eae1fb480ed7ce82a699ddb6)
10b57cec5SDimitry Andric// -*- C++ -*-
2349cc55cSDimitry Andric//===----------------------------------------------------------------------===//
30b57cec5SDimitry Andric//
40b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
50b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information.
60b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
70b57cec5SDimitry Andric//
80b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
90b57cec5SDimitry Andric
100b57cec5SDimitry Andric#ifndef _LIBCPP_COMPLEX
110b57cec5SDimitry Andric#define _LIBCPP_COMPLEX
120b57cec5SDimitry Andric
130b57cec5SDimitry Andric/*
140b57cec5SDimitry Andric    complex synopsis
150b57cec5SDimitry Andric
160b57cec5SDimitry Andricnamespace std
170b57cec5SDimitry Andric{
180b57cec5SDimitry Andric
190b57cec5SDimitry Andrictemplate<class T>
200b57cec5SDimitry Andricclass complex
210b57cec5SDimitry Andric{
220b57cec5SDimitry Andricpublic:
230b57cec5SDimitry Andric    typedef T value_type;
240b57cec5SDimitry Andric
250b57cec5SDimitry Andric    complex(const T& re = T(), const T& im = T()); // constexpr in C++14
260b57cec5SDimitry Andric    complex(const complex&);  // constexpr in C++14
270b57cec5SDimitry Andric    template<class X> complex(const complex<X>&);  // constexpr in C++14
280b57cec5SDimitry Andric
290b57cec5SDimitry Andric    T real() const; // constexpr in C++14
300b57cec5SDimitry Andric    T imag() const; // constexpr in C++14
310b57cec5SDimitry Andric
32bdd1243dSDimitry Andric    void real(T); // constexpr in C++20
33bdd1243dSDimitry Andric    void imag(T); // constexpr in C++20
340b57cec5SDimitry Andric
35bdd1243dSDimitry Andric    complex<T>& operator= (const T&); // constexpr in C++20
36bdd1243dSDimitry Andric    complex<T>& operator+=(const T&); // constexpr in C++20
37bdd1243dSDimitry Andric    complex<T>& operator-=(const T&); // constexpr in C++20
38bdd1243dSDimitry Andric    complex<T>& operator*=(const T&); // constexpr in C++20
39bdd1243dSDimitry Andric    complex<T>& operator/=(const T&); // constexpr in C++20
400b57cec5SDimitry Andric
41bdd1243dSDimitry Andric    complex& operator=(const complex&); // constexpr in C++20
42bdd1243dSDimitry Andric    template<class X> complex<T>& operator= (const complex<X>&); // constexpr in C++20
43bdd1243dSDimitry Andric    template<class X> complex<T>& operator+=(const complex<X>&); // constexpr in C++20
44bdd1243dSDimitry Andric    template<class X> complex<T>& operator-=(const complex<X>&); // constexpr in C++20
45bdd1243dSDimitry Andric    template<class X> complex<T>& operator*=(const complex<X>&); // constexpr in C++20
46bdd1243dSDimitry Andric    template<class X> complex<T>& operator/=(const complex<X>&); // constexpr in C++20
470b57cec5SDimitry Andric};
480b57cec5SDimitry Andric
490b57cec5SDimitry Andrictemplate<>
500b57cec5SDimitry Andricclass complex<float>
510b57cec5SDimitry Andric{
520b57cec5SDimitry Andricpublic:
530b57cec5SDimitry Andric    typedef float value_type;
540b57cec5SDimitry Andric
550b57cec5SDimitry Andric    constexpr complex(float re = 0.0f, float im = 0.0f);
560b57cec5SDimitry Andric    explicit constexpr complex(const complex<double>&);
570b57cec5SDimitry Andric    explicit constexpr complex(const complex<long double>&);
580b57cec5SDimitry Andric
590b57cec5SDimitry Andric    constexpr float real() const;
60bdd1243dSDimitry Andric    void real(float); // constexpr in C++20
610b57cec5SDimitry Andric    constexpr float imag() const;
62bdd1243dSDimitry Andric    void imag(float); // constexpr in C++20
630b57cec5SDimitry Andric
64bdd1243dSDimitry Andric    complex<float>& operator= (float); // constexpr in C++20
65bdd1243dSDimitry Andric    complex<float>& operator+=(float); // constexpr in C++20
66bdd1243dSDimitry Andric    complex<float>& operator-=(float); // constexpr in C++20
67bdd1243dSDimitry Andric    complex<float>& operator*=(float); // constexpr in C++20
68bdd1243dSDimitry Andric    complex<float>& operator/=(float); // constexpr in C++20
690b57cec5SDimitry Andric
70bdd1243dSDimitry Andric    complex<float>& operator=(const complex<float>&); // constexpr in C++20
71bdd1243dSDimitry Andric    template<class X> complex<float>& operator= (const complex<X>&); // constexpr in C++20
72bdd1243dSDimitry Andric    template<class X> complex<float>& operator+=(const complex<X>&); // constexpr in C++20
73bdd1243dSDimitry Andric    template<class X> complex<float>& operator-=(const complex<X>&); // constexpr in C++20
74bdd1243dSDimitry Andric    template<class X> complex<float>& operator*=(const complex<X>&); // constexpr in C++20
75bdd1243dSDimitry Andric    template<class X> complex<float>& operator/=(const complex<X>&); // constexpr in C++20
760b57cec5SDimitry Andric};
770b57cec5SDimitry Andric
780b57cec5SDimitry Andrictemplate<>
790b57cec5SDimitry Andricclass complex<double>
800b57cec5SDimitry Andric{
810b57cec5SDimitry Andricpublic:
820b57cec5SDimitry Andric    typedef double value_type;
830b57cec5SDimitry Andric
840b57cec5SDimitry Andric    constexpr complex(double re = 0.0, double im = 0.0);
850b57cec5SDimitry Andric    constexpr complex(const complex<float>&);
860b57cec5SDimitry Andric    explicit constexpr complex(const complex<long double>&);
870b57cec5SDimitry Andric
880b57cec5SDimitry Andric    constexpr double real() const;
89bdd1243dSDimitry Andric    void real(double); // constexpr in C++20
900b57cec5SDimitry Andric    constexpr double imag() const;
91bdd1243dSDimitry Andric    void imag(double); // constexpr in C++20
920b57cec5SDimitry Andric
93bdd1243dSDimitry Andric    complex<double>& operator= (double); // constexpr in C++20
94bdd1243dSDimitry Andric    complex<double>& operator+=(double); // constexpr in C++20
95bdd1243dSDimitry Andric    complex<double>& operator-=(double); // constexpr in C++20
96bdd1243dSDimitry Andric    complex<double>& operator*=(double); // constexpr in C++20
97bdd1243dSDimitry Andric    complex<double>& operator/=(double); // constexpr in C++20
98bdd1243dSDimitry Andric    complex<double>& operator=(const complex<double>&); // constexpr in C++20
990b57cec5SDimitry Andric
100bdd1243dSDimitry Andric    template<class X> complex<double>& operator= (const complex<X>&); // constexpr in C++20
101bdd1243dSDimitry Andric    template<class X> complex<double>& operator+=(const complex<X>&); // constexpr in C++20
102bdd1243dSDimitry Andric    template<class X> complex<double>& operator-=(const complex<X>&); // constexpr in C++20
103bdd1243dSDimitry Andric    template<class X> complex<double>& operator*=(const complex<X>&); // constexpr in C++20
104bdd1243dSDimitry Andric    template<class X> complex<double>& operator/=(const complex<X>&); // constexpr in C++20
1050b57cec5SDimitry Andric};
1060b57cec5SDimitry Andric
1070b57cec5SDimitry Andrictemplate<>
1080b57cec5SDimitry Andricclass complex<long double>
1090b57cec5SDimitry Andric{
1100b57cec5SDimitry Andricpublic:
1110b57cec5SDimitry Andric    typedef long double value_type;
1120b57cec5SDimitry Andric
1130b57cec5SDimitry Andric    constexpr complex(long double re = 0.0L, long double im = 0.0L);
1140b57cec5SDimitry Andric    constexpr complex(const complex<float>&);
1150b57cec5SDimitry Andric    constexpr complex(const complex<double>&);
1160b57cec5SDimitry Andric
1170b57cec5SDimitry Andric    constexpr long double real() const;
118bdd1243dSDimitry Andric    void real(long double); // constexpr in C++20
1190b57cec5SDimitry Andric    constexpr long double imag() const;
120bdd1243dSDimitry Andric    void imag(long double); // constexpr in C++20
1210b57cec5SDimitry Andric
122bdd1243dSDimitry Andric    complex<long double>& operator=(const complex<long double>&); // constexpr in C++20
123bdd1243dSDimitry Andric    complex<long double>& operator= (long double); // constexpr in C++20
124bdd1243dSDimitry Andric    complex<long double>& operator+=(long double); // constexpr in C++20
125bdd1243dSDimitry Andric    complex<long double>& operator-=(long double); // constexpr in C++20
126bdd1243dSDimitry Andric    complex<long double>& operator*=(long double); // constexpr in C++20
127bdd1243dSDimitry Andric    complex<long double>& operator/=(long double); // constexpr in C++20
1280b57cec5SDimitry Andric
129bdd1243dSDimitry Andric    template<class X> complex<long double>& operator= (const complex<X>&); // constexpr in C++20
130bdd1243dSDimitry Andric    template<class X> complex<long double>& operator+=(const complex<X>&); // constexpr in C++20
131bdd1243dSDimitry Andric    template<class X> complex<long double>& operator-=(const complex<X>&); // constexpr in C++20
132bdd1243dSDimitry Andric    template<class X> complex<long double>& operator*=(const complex<X>&); // constexpr in C++20
133bdd1243dSDimitry Andric    template<class X> complex<long double>& operator/=(const complex<X>&); // constexpr in C++20
1340b57cec5SDimitry Andric};
1350b57cec5SDimitry Andric
1360b57cec5SDimitry Andric// 26.3.6 operators:
137bdd1243dSDimitry Andrictemplate<class T> complex<T> operator+(const complex<T>&, const complex<T>&); // constexpr in C++20
138bdd1243dSDimitry Andrictemplate<class T> complex<T> operator+(const complex<T>&, const T&);          // constexpr in C++20
139bdd1243dSDimitry Andrictemplate<class T> complex<T> operator+(const T&, const complex<T>&);          // constexpr in C++20
140bdd1243dSDimitry Andrictemplate<class T> complex<T> operator-(const complex<T>&, const complex<T>&); // constexpr in C++20
141bdd1243dSDimitry Andrictemplate<class T> complex<T> operator-(const complex<T>&, const T&);          // constexpr in C++20
142bdd1243dSDimitry Andrictemplate<class T> complex<T> operator-(const T&, const complex<T>&);          // constexpr in C++20
143bdd1243dSDimitry Andrictemplate<class T> complex<T> operator*(const complex<T>&, const complex<T>&); // constexpr in C++20
144bdd1243dSDimitry Andrictemplate<class T> complex<T> operator*(const complex<T>&, const T&);          // constexpr in C++20
145bdd1243dSDimitry Andrictemplate<class T> complex<T> operator*(const T&, const complex<T>&);          // constexpr in C++20
146bdd1243dSDimitry Andrictemplate<class T> complex<T> operator/(const complex<T>&, const complex<T>&); // constexpr in C++20
147bdd1243dSDimitry Andrictemplate<class T> complex<T> operator/(const complex<T>&, const T&);          // constexpr in C++20
148bdd1243dSDimitry Andrictemplate<class T> complex<T> operator/(const T&, const complex<T>&);          // constexpr in C++20
149bdd1243dSDimitry Andrictemplate<class T> complex<T> operator+(const complex<T>&);                    // constexpr in C++20
150bdd1243dSDimitry Andrictemplate<class T> complex<T> operator-(const complex<T>&);                    // constexpr in C++20
1510b57cec5SDimitry Andrictemplate<class T> bool operator==(const complex<T>&, const complex<T>&);      // constexpr in C++14
1520b57cec5SDimitry Andrictemplate<class T> bool operator==(const complex<T>&, const T&);               // constexpr in C++14
15306c3fb27SDimitry Andrictemplate<class T> bool operator==(const T&, const complex<T>&);               // constexpr in C++14, removed in C++20
15406c3fb27SDimitry Andrictemplate<class T> bool operator!=(const complex<T>&, const complex<T>&);      // constexpr in C++14, removed in C++20
15506c3fb27SDimitry Andrictemplate<class T> bool operator!=(const complex<T>&, const T&);               // constexpr in C++14, removed in C++20
15606c3fb27SDimitry Andrictemplate<class T> bool operator!=(const T&, const complex<T>&);               // constexpr in C++14, removed in C++20
1570b57cec5SDimitry Andric
1580b57cec5SDimitry Andrictemplate<class T, class charT, class traits>
1590b57cec5SDimitry Andric  basic_istream<charT, traits>&
1600b57cec5SDimitry Andric  operator>>(basic_istream<charT, traits>&, complex<T>&);
1610b57cec5SDimitry Andrictemplate<class T, class charT, class traits>
1620b57cec5SDimitry Andric  basic_ostream<charT, traits>&
1630b57cec5SDimitry Andric  operator<<(basic_ostream<charT, traits>&, const complex<T>&);
1640b57cec5SDimitry Andric
1650b57cec5SDimitry Andric// 26.3.7 values:
1660b57cec5SDimitry Andric
1670b57cec5SDimitry Andrictemplate<class T>              T real(const complex<T>&); // constexpr in C++14
1680b57cec5SDimitry Andric                     long double real(long double);       // constexpr in C++14
1690b57cec5SDimitry Andric                          double real(double);            // constexpr in C++14
1700b57cec5SDimitry Andrictemplate<Integral T>      double real(T);                 // constexpr in C++14
1710b57cec5SDimitry Andric                          float  real(float);             // constexpr in C++14
1720b57cec5SDimitry Andric
1730b57cec5SDimitry Andrictemplate<class T>              T imag(const complex<T>&); // constexpr in C++14
1740b57cec5SDimitry Andric                     long double imag(long double);       // constexpr in C++14
1750b57cec5SDimitry Andric                          double imag(double);            // constexpr in C++14
1760b57cec5SDimitry Andrictemplate<Integral T>      double imag(T);                 // constexpr in C++14
1770b57cec5SDimitry Andric                          float  imag(float);             // constexpr in C++14
1780b57cec5SDimitry Andric
1790b57cec5SDimitry Andrictemplate<class T> T abs(const complex<T>&);
1800b57cec5SDimitry Andric
1810b57cec5SDimitry Andrictemplate<class T>              T arg(const complex<T>&);
1820b57cec5SDimitry Andric                     long double arg(long double);
1830b57cec5SDimitry Andric                          double arg(double);
1840b57cec5SDimitry Andrictemplate<Integral T>      double arg(T);
1850b57cec5SDimitry Andric                          float  arg(float);
1860b57cec5SDimitry Andric
187bdd1243dSDimitry Andrictemplate<class T>              T norm(const complex<T>&); // constexpr in C++20
188bdd1243dSDimitry Andric                     long double norm(long double);       // constexpr in C++20
189bdd1243dSDimitry Andric                          double norm(double);            // constexpr in C++20
190bdd1243dSDimitry Andrictemplate<Integral T>      double norm(T);                 // constexpr in C++20
191bdd1243dSDimitry Andric                          float  norm(float);             // constexpr in C++20
1920b57cec5SDimitry Andric
193bdd1243dSDimitry Andrictemplate<class T>      complex<T>           conj(const complex<T>&); // constexpr in C++20
194bdd1243dSDimitry Andric                       complex<long double> conj(long double);       // constexpr in C++20
195bdd1243dSDimitry Andric                       complex<double>      conj(double);            // constexpr in C++20
196bdd1243dSDimitry Andrictemplate<Integral T>   complex<double>      conj(T);                 // constexpr in C++20
197bdd1243dSDimitry Andric                       complex<float>       conj(float);             // constexpr in C++20
1980b57cec5SDimitry Andric
1990b57cec5SDimitry Andrictemplate<class T>    complex<T>           proj(const complex<T>&);
2000b57cec5SDimitry Andric                     complex<long double> proj(long double);
2010b57cec5SDimitry Andric                     complex<double>      proj(double);
2020b57cec5SDimitry Andrictemplate<Integral T> complex<double>      proj(T);
2030b57cec5SDimitry Andric                     complex<float>       proj(float);
2040b57cec5SDimitry Andric
2050b57cec5SDimitry Andrictemplate<class T> complex<T> polar(const T&, const T& = T());
2060b57cec5SDimitry Andric
2070b57cec5SDimitry Andric// 26.3.8 transcendentals:
2080b57cec5SDimitry Andrictemplate<class T> complex<T> acos(const complex<T>&);
2090b57cec5SDimitry Andrictemplate<class T> complex<T> asin(const complex<T>&);
2100b57cec5SDimitry Andrictemplate<class T> complex<T> atan(const complex<T>&);
2110b57cec5SDimitry Andrictemplate<class T> complex<T> acosh(const complex<T>&);
2120b57cec5SDimitry Andrictemplate<class T> complex<T> asinh(const complex<T>&);
2130b57cec5SDimitry Andrictemplate<class T> complex<T> atanh(const complex<T>&);
2140b57cec5SDimitry Andrictemplate<class T> complex<T> cos (const complex<T>&);
2150b57cec5SDimitry Andrictemplate<class T> complex<T> cosh (const complex<T>&);
2160b57cec5SDimitry Andrictemplate<class T> complex<T> exp (const complex<T>&);
2170b57cec5SDimitry Andrictemplate<class T> complex<T> log (const complex<T>&);
2180b57cec5SDimitry Andrictemplate<class T> complex<T> log10(const complex<T>&);
2190b57cec5SDimitry Andric
2200b57cec5SDimitry Andrictemplate<class T> complex<T> pow(const complex<T>&, const T&);
2210b57cec5SDimitry Andrictemplate<class T> complex<T> pow(const complex<T>&, const complex<T>&);
2220b57cec5SDimitry Andrictemplate<class T> complex<T> pow(const T&, const complex<T>&);
2230b57cec5SDimitry Andric
2240b57cec5SDimitry Andrictemplate<class T> complex<T> sin (const complex<T>&);
2250b57cec5SDimitry Andrictemplate<class T> complex<T> sinh (const complex<T>&);
2260b57cec5SDimitry Andrictemplate<class T> complex<T> sqrt (const complex<T>&);
2270b57cec5SDimitry Andrictemplate<class T> complex<T> tan (const complex<T>&);
2280b57cec5SDimitry Andrictemplate<class T> complex<T> tanh (const complex<T>&);
2290b57cec5SDimitry Andric
2300b57cec5SDimitry Andric}  // std
2310b57cec5SDimitry Andric
2320b57cec5SDimitry Andric*/
2330b57cec5SDimitry Andric
23481ad6265SDimitry Andric#include <__assert> // all public C++ headers provide the assertion handler
2350b57cec5SDimitry Andric#include <__config>
2360b57cec5SDimitry Andric#include <cmath>
2370b57cec5SDimitry Andric#include <version>
2380b57cec5SDimitry Andric
239e8d8bef9SDimitry Andric#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
240e8d8bef9SDimitry Andric#  include <sstream> // for std::basic_ostringstream
241e8d8bef9SDimitry Andric#endif
242e8d8bef9SDimitry Andric
2430b57cec5SDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
2440b57cec5SDimitry Andric#  pragma GCC system_header
2450b57cec5SDimitry Andric#endif
2460b57cec5SDimitry Andric
2470b57cec5SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD
2480b57cec5SDimitry Andric
249*cb14a3feSDimitry Andrictemplate <class _Tp>
250*cb14a3feSDimitry Andricclass _LIBCPP_TEMPLATE_VIS complex;
2510b57cec5SDimitry Andric
2520b57cec5SDimitry Andrictemplate <class _Tp>
253*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
254*cb14a3feSDimitry Andricoperator*(const complex<_Tp>& __z, const complex<_Tp>& __w);
255*cb14a3feSDimitry Andrictemplate <class _Tp>
256*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
257*cb14a3feSDimitry Andricoperator/(const complex<_Tp>& __x, const complex<_Tp>& __y);
258*cb14a3feSDimitry Andric
259*cb14a3feSDimitry Andrictemplate <class _Tp>
260*cb14a3feSDimitry Andricclass _LIBCPP_TEMPLATE_VIS complex {
2610b57cec5SDimitry Andricpublic:
2620b57cec5SDimitry Andric  typedef _Tp value_type;
263*cb14a3feSDimitry Andric
2640b57cec5SDimitry Andricprivate:
2650b57cec5SDimitry Andric  value_type __re_;
2660b57cec5SDimitry Andric  value_type __im_;
267*cb14a3feSDimitry Andric
2680b57cec5SDimitry Andricpublic:
2695f757f3fSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
2700b57cec5SDimitry Andric  complex(const value_type& __re = value_type(), const value_type& __im = value_type())
2710b57cec5SDimitry Andric      : __re_(__re), __im_(__im) {}
272*cb14a3feSDimitry Andric  template <class _Xp>
273*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 complex(const complex<_Xp>& __c)
2740b57cec5SDimitry Andric      : __re_(__c.real()), __im_(__c.imag()) {}
2750b57cec5SDimitry Andric
2765f757f3fSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 value_type real() const { return __re_; }
2775f757f3fSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 value_type imag() const { return __im_; }
2780b57cec5SDimitry Andric
2795f757f3fSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void real(value_type __re) { __re_ = __re; }
2805f757f3fSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void imag(value_type __im) { __im_ = __im; }
2810b57cec5SDimitry Andric
282*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator=(const value_type& __re) {
283*cb14a3feSDimitry Andric    __re_ = __re;
284*cb14a3feSDimitry Andric    __im_ = value_type();
285*cb14a3feSDimitry Andric    return *this;
286*cb14a3feSDimitry Andric  }
287*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator+=(const value_type& __re) {
288*cb14a3feSDimitry Andric    __re_ += __re;
289*cb14a3feSDimitry Andric    return *this;
290*cb14a3feSDimitry Andric  }
291*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator-=(const value_type& __re) {
292*cb14a3feSDimitry Andric    __re_ -= __re;
293*cb14a3feSDimitry Andric    return *this;
294*cb14a3feSDimitry Andric  }
295*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator*=(const value_type& __re) {
296*cb14a3feSDimitry Andric    __re_ *= __re;
297*cb14a3feSDimitry Andric    __im_ *= __re;
298*cb14a3feSDimitry Andric    return *this;
299*cb14a3feSDimitry Andric  }
300*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator/=(const value_type& __re) {
301*cb14a3feSDimitry Andric    __re_ /= __re;
302*cb14a3feSDimitry Andric    __im_ /= __re;
303*cb14a3feSDimitry Andric    return *this;
304*cb14a3feSDimitry Andric  }
3050b57cec5SDimitry Andric
306*cb14a3feSDimitry Andric  template <class _Xp>
307*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator=(const complex<_Xp>& __c) {
3080b57cec5SDimitry Andric    __re_ = __c.real();
3090b57cec5SDimitry Andric    __im_ = __c.imag();
3100b57cec5SDimitry Andric    return *this;
3110b57cec5SDimitry Andric  }
312*cb14a3feSDimitry Andric  template <class _Xp>
313*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator+=(const complex<_Xp>& __c) {
3140b57cec5SDimitry Andric    __re_ += __c.real();
3150b57cec5SDimitry Andric    __im_ += __c.imag();
3160b57cec5SDimitry Andric    return *this;
3170b57cec5SDimitry Andric  }
318*cb14a3feSDimitry Andric  template <class _Xp>
319*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator-=(const complex<_Xp>& __c) {
3200b57cec5SDimitry Andric    __re_ -= __c.real();
3210b57cec5SDimitry Andric    __im_ -= __c.imag();
3220b57cec5SDimitry Andric    return *this;
3230b57cec5SDimitry Andric  }
324*cb14a3feSDimitry Andric  template <class _Xp>
325*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator*=(const complex<_Xp>& __c) {
3260b57cec5SDimitry Andric    *this = *this * complex(__c.real(), __c.imag());
3270b57cec5SDimitry Andric    return *this;
3280b57cec5SDimitry Andric  }
329*cb14a3feSDimitry Andric  template <class _Xp>
330*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator/=(const complex<_Xp>& __c) {
3310b57cec5SDimitry Andric    *this = *this / complex(__c.real(), __c.imag());
3320b57cec5SDimitry Andric    return *this;
3330b57cec5SDimitry Andric  }
3340b57cec5SDimitry Andric};
3350b57cec5SDimitry Andric
336*cb14a3feSDimitry Andrictemplate <>
337*cb14a3feSDimitry Andricclass _LIBCPP_TEMPLATE_VIS complex<double>;
338*cb14a3feSDimitry Andrictemplate <>
339*cb14a3feSDimitry Andricclass _LIBCPP_TEMPLATE_VIS complex<long double>;
3400b57cec5SDimitry Andric
3410b57cec5SDimitry Andrictemplate <>
342*cb14a3feSDimitry Andricclass _LIBCPP_TEMPLATE_VIS complex<float> {
3430b57cec5SDimitry Andric  float __re_;
3440b57cec5SDimitry Andric  float __im_;
345*cb14a3feSDimitry Andric
3460b57cec5SDimitry Andricpublic:
3470b57cec5SDimitry Andric  typedef float value_type;
3480b57cec5SDimitry Andric
349*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR complex(float __re = 0.0f, float __im = 0.0f) : __re_(__re), __im_(__im) {}
350*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI explicit _LIBCPP_CONSTEXPR complex(const complex<double>& __c);
351*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI explicit _LIBCPP_CONSTEXPR complex(const complex<long double>& __c);
3520b57cec5SDimitry Andric
3535f757f3fSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR float real() const { return __re_; }
3545f757f3fSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR float imag() const { return __im_; }
3550b57cec5SDimitry Andric
3565f757f3fSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void real(value_type __re) { __re_ = __re; }
3575f757f3fSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void imag(value_type __im) { __im_ = __im; }
3580b57cec5SDimitry Andric
359*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator=(float __re) {
360*cb14a3feSDimitry Andric    __re_ = __re;
361*cb14a3feSDimitry Andric    __im_ = value_type();
362*cb14a3feSDimitry Andric    return *this;
363*cb14a3feSDimitry Andric  }
364*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator+=(float __re) {
365*cb14a3feSDimitry Andric    __re_ += __re;
366*cb14a3feSDimitry Andric    return *this;
367*cb14a3feSDimitry Andric  }
368*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator-=(float __re) {
369*cb14a3feSDimitry Andric    __re_ -= __re;
370*cb14a3feSDimitry Andric    return *this;
371*cb14a3feSDimitry Andric  }
372*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator*=(float __re) {
373*cb14a3feSDimitry Andric    __re_ *= __re;
374*cb14a3feSDimitry Andric    __im_ *= __re;
375*cb14a3feSDimitry Andric    return *this;
376*cb14a3feSDimitry Andric  }
377*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator/=(float __re) {
378*cb14a3feSDimitry Andric    __re_ /= __re;
379*cb14a3feSDimitry Andric    __im_ /= __re;
380*cb14a3feSDimitry Andric    return *this;
381*cb14a3feSDimitry Andric  }
3820b57cec5SDimitry Andric
383*cb14a3feSDimitry Andric  template <class _Xp>
384*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator=(const complex<_Xp>& __c) {
3850b57cec5SDimitry Andric    __re_ = __c.real();
3860b57cec5SDimitry Andric    __im_ = __c.imag();
3870b57cec5SDimitry Andric    return *this;
3880b57cec5SDimitry Andric  }
389*cb14a3feSDimitry Andric  template <class _Xp>
390*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator+=(const complex<_Xp>& __c) {
3910b57cec5SDimitry Andric    __re_ += __c.real();
3920b57cec5SDimitry Andric    __im_ += __c.imag();
3930b57cec5SDimitry Andric    return *this;
3940b57cec5SDimitry Andric  }
395*cb14a3feSDimitry Andric  template <class _Xp>
396*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator-=(const complex<_Xp>& __c) {
3970b57cec5SDimitry Andric    __re_ -= __c.real();
3980b57cec5SDimitry Andric    __im_ -= __c.imag();
3990b57cec5SDimitry Andric    return *this;
4000b57cec5SDimitry Andric  }
401*cb14a3feSDimitry Andric  template <class _Xp>
402*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator*=(const complex<_Xp>& __c) {
4030b57cec5SDimitry Andric    *this = *this * complex(__c.real(), __c.imag());
4040b57cec5SDimitry Andric    return *this;
4050b57cec5SDimitry Andric  }
406*cb14a3feSDimitry Andric  template <class _Xp>
407*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator/=(const complex<_Xp>& __c) {
4080b57cec5SDimitry Andric    *this = *this / complex(__c.real(), __c.imag());
4090b57cec5SDimitry Andric    return *this;
4100b57cec5SDimitry Andric  }
4110b57cec5SDimitry Andric};
4120b57cec5SDimitry Andric
4130b57cec5SDimitry Andrictemplate <>
414*cb14a3feSDimitry Andricclass _LIBCPP_TEMPLATE_VIS complex<double> {
4150b57cec5SDimitry Andric  double __re_;
4160b57cec5SDimitry Andric  double __im_;
417*cb14a3feSDimitry Andric
4180b57cec5SDimitry Andricpublic:
4190b57cec5SDimitry Andric  typedef double value_type;
4200b57cec5SDimitry Andric
421*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR complex(double __re = 0.0, double __im = 0.0) : __re_(__re), __im_(__im) {}
422*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR complex(const complex<float>& __c);
423*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI explicit _LIBCPP_CONSTEXPR complex(const complex<long double>& __c);
4240b57cec5SDimitry Andric
4255f757f3fSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR double real() const { return __re_; }
4265f757f3fSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR double imag() const { return __im_; }
4270b57cec5SDimitry Andric
4285f757f3fSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void real(value_type __re) { __re_ = __re; }
4295f757f3fSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void imag(value_type __im) { __im_ = __im; }
4300b57cec5SDimitry Andric
431*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator=(double __re) {
432*cb14a3feSDimitry Andric    __re_ = __re;
433*cb14a3feSDimitry Andric    __im_ = value_type();
434*cb14a3feSDimitry Andric    return *this;
435*cb14a3feSDimitry Andric  }
436*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator+=(double __re) {
437*cb14a3feSDimitry Andric    __re_ += __re;
438*cb14a3feSDimitry Andric    return *this;
439*cb14a3feSDimitry Andric  }
440*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator-=(double __re) {
441*cb14a3feSDimitry Andric    __re_ -= __re;
442*cb14a3feSDimitry Andric    return *this;
443*cb14a3feSDimitry Andric  }
444*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator*=(double __re) {
445*cb14a3feSDimitry Andric    __re_ *= __re;
446*cb14a3feSDimitry Andric    __im_ *= __re;
447*cb14a3feSDimitry Andric    return *this;
448*cb14a3feSDimitry Andric  }
449*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator/=(double __re) {
450*cb14a3feSDimitry Andric    __re_ /= __re;
451*cb14a3feSDimitry Andric    __im_ /= __re;
452*cb14a3feSDimitry Andric    return *this;
453*cb14a3feSDimitry Andric  }
4540b57cec5SDimitry Andric
455*cb14a3feSDimitry Andric  template <class _Xp>
456*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator=(const complex<_Xp>& __c) {
4570b57cec5SDimitry Andric    __re_ = __c.real();
4580b57cec5SDimitry Andric    __im_ = __c.imag();
4590b57cec5SDimitry Andric    return *this;
4600b57cec5SDimitry Andric  }
461*cb14a3feSDimitry Andric  template <class _Xp>
462*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator+=(const complex<_Xp>& __c) {
4630b57cec5SDimitry Andric    __re_ += __c.real();
4640b57cec5SDimitry Andric    __im_ += __c.imag();
4650b57cec5SDimitry Andric    return *this;
4660b57cec5SDimitry Andric  }
467*cb14a3feSDimitry Andric  template <class _Xp>
468*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator-=(const complex<_Xp>& __c) {
4690b57cec5SDimitry Andric    __re_ -= __c.real();
4700b57cec5SDimitry Andric    __im_ -= __c.imag();
4710b57cec5SDimitry Andric    return *this;
4720b57cec5SDimitry Andric  }
473*cb14a3feSDimitry Andric  template <class _Xp>
474*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator*=(const complex<_Xp>& __c) {
4750b57cec5SDimitry Andric    *this = *this * complex(__c.real(), __c.imag());
4760b57cec5SDimitry Andric    return *this;
4770b57cec5SDimitry Andric  }
478*cb14a3feSDimitry Andric  template <class _Xp>
479*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator/=(const complex<_Xp>& __c) {
4800b57cec5SDimitry Andric    *this = *this / complex(__c.real(), __c.imag());
4810b57cec5SDimitry Andric    return *this;
4820b57cec5SDimitry Andric  }
4830b57cec5SDimitry Andric};
4840b57cec5SDimitry Andric
4850b57cec5SDimitry Andrictemplate <>
486*cb14a3feSDimitry Andricclass _LIBCPP_TEMPLATE_VIS complex<long double> {
4870b57cec5SDimitry Andric  long double __re_;
4880b57cec5SDimitry Andric  long double __im_;
489*cb14a3feSDimitry Andric
4900b57cec5SDimitry Andricpublic:
4910b57cec5SDimitry Andric  typedef long double value_type;
4920b57cec5SDimitry Andric
4935f757f3fSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR complex(long double __re = 0.0L, long double __im = 0.0L)
4940b57cec5SDimitry Andric      : __re_(__re), __im_(__im) {}
495*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR complex(const complex<float>& __c);
496*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR complex(const complex<double>& __c);
4970b57cec5SDimitry Andric
4985f757f3fSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR long double real() const { return __re_; }
4995f757f3fSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR long double imag() const { return __im_; }
5000b57cec5SDimitry Andric
5015f757f3fSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void real(value_type __re) { __re_ = __re; }
5025f757f3fSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void imag(value_type __im) { __im_ = __im; }
5030b57cec5SDimitry Andric
504*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator=(long double __re) {
505*cb14a3feSDimitry Andric    __re_ = __re;
506*cb14a3feSDimitry Andric    __im_ = value_type();
507*cb14a3feSDimitry Andric    return *this;
508*cb14a3feSDimitry Andric  }
509*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator+=(long double __re) {
510*cb14a3feSDimitry Andric    __re_ += __re;
511*cb14a3feSDimitry Andric    return *this;
512*cb14a3feSDimitry Andric  }
513*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator-=(long double __re) {
514*cb14a3feSDimitry Andric    __re_ -= __re;
515*cb14a3feSDimitry Andric    return *this;
516*cb14a3feSDimitry Andric  }
517*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator*=(long double __re) {
518*cb14a3feSDimitry Andric    __re_ *= __re;
519*cb14a3feSDimitry Andric    __im_ *= __re;
520*cb14a3feSDimitry Andric    return *this;
521*cb14a3feSDimitry Andric  }
522*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator/=(long double __re) {
523*cb14a3feSDimitry Andric    __re_ /= __re;
524*cb14a3feSDimitry Andric    __im_ /= __re;
525*cb14a3feSDimitry Andric    return *this;
526*cb14a3feSDimitry Andric  }
5270b57cec5SDimitry Andric
528*cb14a3feSDimitry Andric  template <class _Xp>
529*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator=(const complex<_Xp>& __c) {
5300b57cec5SDimitry Andric    __re_ = __c.real();
5310b57cec5SDimitry Andric    __im_ = __c.imag();
5320b57cec5SDimitry Andric    return *this;
5330b57cec5SDimitry Andric  }
534*cb14a3feSDimitry Andric  template <class _Xp>
535*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator+=(const complex<_Xp>& __c) {
5360b57cec5SDimitry Andric    __re_ += __c.real();
5370b57cec5SDimitry Andric    __im_ += __c.imag();
5380b57cec5SDimitry Andric    return *this;
5390b57cec5SDimitry Andric  }
540*cb14a3feSDimitry Andric  template <class _Xp>
541*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator-=(const complex<_Xp>& __c) {
5420b57cec5SDimitry Andric    __re_ -= __c.real();
5430b57cec5SDimitry Andric    __im_ -= __c.imag();
5440b57cec5SDimitry Andric    return *this;
5450b57cec5SDimitry Andric  }
546*cb14a3feSDimitry Andric  template <class _Xp>
547*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator*=(const complex<_Xp>& __c) {
5480b57cec5SDimitry Andric    *this = *this * complex(__c.real(), __c.imag());
5490b57cec5SDimitry Andric    return *this;
5500b57cec5SDimitry Andric  }
551*cb14a3feSDimitry Andric  template <class _Xp>
552*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator/=(const complex<_Xp>& __c) {
5530b57cec5SDimitry Andric    *this = *this / complex(__c.real(), __c.imag());
5540b57cec5SDimitry Andric    return *this;
5550b57cec5SDimitry Andric  }
5560b57cec5SDimitry Andric};
5570b57cec5SDimitry Andric
558*cb14a3feSDimitry Andricinline _LIBCPP_CONSTEXPR complex<float>::complex(const complex<double>& __c) : __re_(__c.real()), __im_(__c.imag()) {}
559*cb14a3feSDimitry Andric
560*cb14a3feSDimitry Andricinline _LIBCPP_CONSTEXPR complex<float>::complex(const complex<long double>& __c)
5610b57cec5SDimitry Andric    : __re_(__c.real()), __im_(__c.imag()) {}
5620b57cec5SDimitry Andric
563*cb14a3feSDimitry Andricinline _LIBCPP_CONSTEXPR complex<double>::complex(const complex<float>& __c) : __re_(__c.real()), __im_(__c.imag()) {}
564*cb14a3feSDimitry Andric
565*cb14a3feSDimitry Andricinline _LIBCPP_CONSTEXPR complex<double>::complex(const complex<long double>& __c)
5660b57cec5SDimitry Andric    : __re_(__c.real()), __im_(__c.imag()) {}
5670b57cec5SDimitry Andric
568*cb14a3feSDimitry Andricinline _LIBCPP_CONSTEXPR complex<long double>::complex(const complex<float>& __c)
5690b57cec5SDimitry Andric    : __re_(__c.real()), __im_(__c.imag()) {}
5700b57cec5SDimitry Andric
571*cb14a3feSDimitry Andricinline _LIBCPP_CONSTEXPR complex<long double>::complex(const complex<double>& __c)
5720b57cec5SDimitry Andric    : __re_(__c.real()), __im_(__c.imag()) {}
5730b57cec5SDimitry Andric
5740b57cec5SDimitry Andric// 26.3.6 operators:
5750b57cec5SDimitry Andric
5760b57cec5SDimitry Andrictemplate <class _Tp>
577*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
578*cb14a3feSDimitry Andricoperator+(const complex<_Tp>& __x, const complex<_Tp>& __y) {
5790b57cec5SDimitry Andric  complex<_Tp> __t(__x);
5800b57cec5SDimitry Andric  __t += __y;
5810b57cec5SDimitry Andric  return __t;
5820b57cec5SDimitry Andric}
5830b57cec5SDimitry Andric
5840b57cec5SDimitry Andrictemplate <class _Tp>
585*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
586*cb14a3feSDimitry Andricoperator+(const complex<_Tp>& __x, const _Tp& __y) {
5870b57cec5SDimitry Andric  complex<_Tp> __t(__x);
5880b57cec5SDimitry Andric  __t += __y;
5890b57cec5SDimitry Andric  return __t;
5900b57cec5SDimitry Andric}
5910b57cec5SDimitry Andric
5920b57cec5SDimitry Andrictemplate <class _Tp>
593*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
594*cb14a3feSDimitry Andricoperator+(const _Tp& __x, const complex<_Tp>& __y) {
5950b57cec5SDimitry Andric  complex<_Tp> __t(__y);
5960b57cec5SDimitry Andric  __t += __x;
5970b57cec5SDimitry Andric  return __t;
5980b57cec5SDimitry Andric}
5990b57cec5SDimitry Andric
6000b57cec5SDimitry Andrictemplate <class _Tp>
601*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
602*cb14a3feSDimitry Andricoperator-(const complex<_Tp>& __x, const complex<_Tp>& __y) {
6030b57cec5SDimitry Andric  complex<_Tp> __t(__x);
6040b57cec5SDimitry Andric  __t -= __y;
6050b57cec5SDimitry Andric  return __t;
6060b57cec5SDimitry Andric}
6070b57cec5SDimitry Andric
6080b57cec5SDimitry Andrictemplate <class _Tp>
609*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
610*cb14a3feSDimitry Andricoperator-(const complex<_Tp>& __x, const _Tp& __y) {
6110b57cec5SDimitry Andric  complex<_Tp> __t(__x);
6120b57cec5SDimitry Andric  __t -= __y;
6130b57cec5SDimitry Andric  return __t;
6140b57cec5SDimitry Andric}
6150b57cec5SDimitry Andric
6160b57cec5SDimitry Andrictemplate <class _Tp>
617*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
618*cb14a3feSDimitry Andricoperator-(const _Tp& __x, const complex<_Tp>& __y) {
6190b57cec5SDimitry Andric  complex<_Tp> __t(-__y);
6200b57cec5SDimitry Andric  __t += __x;
6210b57cec5SDimitry Andric  return __t;
6220b57cec5SDimitry Andric}
6230b57cec5SDimitry Andric
6240b57cec5SDimitry Andrictemplate <class _Tp>
625bdd1243dSDimitry Andric_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
626*cb14a3feSDimitry Andricoperator*(const complex<_Tp>& __z, const complex<_Tp>& __w) {
6270b57cec5SDimitry Andric  _Tp __a = __z.real();
6280b57cec5SDimitry Andric  _Tp __b = __z.imag();
6290b57cec5SDimitry Andric  _Tp __c = __w.real();
6300b57cec5SDimitry Andric  _Tp __d = __w.imag();
631bdd1243dSDimitry Andric
632bdd1243dSDimitry Andric  // Avoid floating point operations that are invalid during constant evaluation
633bdd1243dSDimitry Andric  if (__libcpp_is_constant_evaluated()) {
634bdd1243dSDimitry Andric    bool __z_zero = __a == _Tp(0) && __b == _Tp(0);
635bdd1243dSDimitry Andric    bool __w_zero = __c == _Tp(0) && __d == _Tp(0);
636bdd1243dSDimitry Andric    bool __z_inf  = std::__constexpr_isinf(__a) || std::__constexpr_isinf(__b);
637bdd1243dSDimitry Andric    bool __w_inf  = std::__constexpr_isinf(__c) || std::__constexpr_isinf(__d);
638*cb14a3feSDimitry Andric    bool __z_nan =
639*cb14a3feSDimitry Andric        !__z_inf && ((std::__constexpr_isnan(__a) && std::__constexpr_isnan(__b)) ||
640*cb14a3feSDimitry Andric                     (std::__constexpr_isnan(__a) && __b == _Tp(0)) || (__a == _Tp(0) && std::__constexpr_isnan(__b)));
641*cb14a3feSDimitry Andric    bool __w_nan =
642*cb14a3feSDimitry Andric        !__w_inf && ((std::__constexpr_isnan(__c) && std::__constexpr_isnan(__d)) ||
643*cb14a3feSDimitry Andric                     (std::__constexpr_isnan(__c) && __d == _Tp(0)) || (__c == _Tp(0) && std::__constexpr_isnan(__d)));
644bdd1243dSDimitry Andric    if (__z_nan || __w_nan) {
645bdd1243dSDimitry Andric      return complex<_Tp>(_Tp(numeric_limits<_Tp>::quiet_NaN()), _Tp(0));
646bdd1243dSDimitry Andric    }
647bdd1243dSDimitry Andric    if (__z_inf || __w_inf) {
648bdd1243dSDimitry Andric      if (__z_zero || __w_zero) {
649bdd1243dSDimitry Andric        return complex<_Tp>(_Tp(numeric_limits<_Tp>::quiet_NaN()), _Tp(0));
650bdd1243dSDimitry Andric      }
651bdd1243dSDimitry Andric      return complex<_Tp>(_Tp(numeric_limits<_Tp>::infinity()), _Tp(numeric_limits<_Tp>::infinity()));
652bdd1243dSDimitry Andric    }
653bdd1243dSDimitry Andric    bool __z_nonzero_nan = !__z_inf && !__z_nan && (std::__constexpr_isnan(__a) || std::__constexpr_isnan(__b));
654bdd1243dSDimitry Andric    bool __w_nonzero_nan = !__w_inf && !__w_nan && (std::__constexpr_isnan(__c) || std::__constexpr_isnan(__d));
655bdd1243dSDimitry Andric    if (__z_nonzero_nan || __w_nonzero_nan) {
656bdd1243dSDimitry Andric      return complex<_Tp>(_Tp(numeric_limits<_Tp>::quiet_NaN()), _Tp(0));
657bdd1243dSDimitry Andric    }
658bdd1243dSDimitry Andric  }
659bdd1243dSDimitry Andric
6600b57cec5SDimitry Andric  _Tp __ac = __a * __c;
6610b57cec5SDimitry Andric  _Tp __bd = __b * __d;
6620b57cec5SDimitry Andric  _Tp __ad = __a * __d;
6630b57cec5SDimitry Andric  _Tp __bc = __b * __c;
6640b57cec5SDimitry Andric  _Tp __x  = __ac - __bd;
6650b57cec5SDimitry Andric  _Tp __y  = __ad + __bc;
666*cb14a3feSDimitry Andric  if (std::__constexpr_isnan(__x) && std::__constexpr_isnan(__y)) {
6670b57cec5SDimitry Andric    bool __recalc = false;
668*cb14a3feSDimitry Andric    if (std::__constexpr_isinf(__a) || std::__constexpr_isinf(__b)) {
669bdd1243dSDimitry Andric      __a = std::__constexpr_copysign(std::__constexpr_isinf(__a) ? _Tp(1) : _Tp(0), __a);
670bdd1243dSDimitry Andric      __b = std::__constexpr_copysign(std::__constexpr_isinf(__b) ? _Tp(1) : _Tp(0), __b);
671bdd1243dSDimitry Andric      if (std::__constexpr_isnan(__c))
672bdd1243dSDimitry Andric        __c = std::__constexpr_copysign(_Tp(0), __c);
673bdd1243dSDimitry Andric      if (std::__constexpr_isnan(__d))
674bdd1243dSDimitry Andric        __d = std::__constexpr_copysign(_Tp(0), __d);
6750b57cec5SDimitry Andric      __recalc = true;
6760b57cec5SDimitry Andric    }
677*cb14a3feSDimitry Andric    if (std::__constexpr_isinf(__c) || std::__constexpr_isinf(__d)) {
678bdd1243dSDimitry Andric      __c = std::__constexpr_copysign(std::__constexpr_isinf(__c) ? _Tp(1) : _Tp(0), __c);
679bdd1243dSDimitry Andric      __d = std::__constexpr_copysign(std::__constexpr_isinf(__d) ? _Tp(1) : _Tp(0), __d);
680bdd1243dSDimitry Andric      if (std::__constexpr_isnan(__a))
681bdd1243dSDimitry Andric        __a = std::__constexpr_copysign(_Tp(0), __a);
682bdd1243dSDimitry Andric      if (std::__constexpr_isnan(__b))
683bdd1243dSDimitry Andric        __b = std::__constexpr_copysign(_Tp(0), __b);
6840b57cec5SDimitry Andric      __recalc = true;
6850b57cec5SDimitry Andric    }
686*cb14a3feSDimitry Andric    if (!__recalc && (std::__constexpr_isinf(__ac) || std::__constexpr_isinf(__bd) || std::__constexpr_isinf(__ad) ||
687*cb14a3feSDimitry Andric                      std::__constexpr_isinf(__bc))) {
688bdd1243dSDimitry Andric      if (std::__constexpr_isnan(__a))
689bdd1243dSDimitry Andric        __a = std::__constexpr_copysign(_Tp(0), __a);
690bdd1243dSDimitry Andric      if (std::__constexpr_isnan(__b))
691bdd1243dSDimitry Andric        __b = std::__constexpr_copysign(_Tp(0), __b);
692bdd1243dSDimitry Andric      if (std::__constexpr_isnan(__c))
693bdd1243dSDimitry Andric        __c = std::__constexpr_copysign(_Tp(0), __c);
694bdd1243dSDimitry Andric      if (std::__constexpr_isnan(__d))
695bdd1243dSDimitry Andric        __d = std::__constexpr_copysign(_Tp(0), __d);
6960b57cec5SDimitry Andric      __recalc = true;
6970b57cec5SDimitry Andric    }
698*cb14a3feSDimitry Andric    if (__recalc) {
6990b57cec5SDimitry Andric      __x = _Tp(INFINITY) * (__a * __c - __b * __d);
7000b57cec5SDimitry Andric      __y = _Tp(INFINITY) * (__a * __d + __b * __c);
7010b57cec5SDimitry Andric    }
7020b57cec5SDimitry Andric  }
7030b57cec5SDimitry Andric  return complex<_Tp>(__x, __y);
7040b57cec5SDimitry Andric}
7050b57cec5SDimitry Andric
7060b57cec5SDimitry Andrictemplate <class _Tp>
707*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
708*cb14a3feSDimitry Andricoperator*(const complex<_Tp>& __x, const _Tp& __y) {
7090b57cec5SDimitry Andric  complex<_Tp> __t(__x);
7100b57cec5SDimitry Andric  __t *= __y;
7110b57cec5SDimitry Andric  return __t;
7120b57cec5SDimitry Andric}
7130b57cec5SDimitry Andric
7140b57cec5SDimitry Andrictemplate <class _Tp>
715*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
716*cb14a3feSDimitry Andricoperator*(const _Tp& __x, const complex<_Tp>& __y) {
7170b57cec5SDimitry Andric  complex<_Tp> __t(__y);
7180b57cec5SDimitry Andric  __t *= __x;
7190b57cec5SDimitry Andric  return __t;
7200b57cec5SDimitry Andric}
7210b57cec5SDimitry Andric
7220b57cec5SDimitry Andrictemplate <class _Tp>
723bdd1243dSDimitry Andric_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
724*cb14a3feSDimitry Andricoperator/(const complex<_Tp>& __z, const complex<_Tp>& __w) {
7250b57cec5SDimitry Andric  int __ilogbw = 0;
7260b57cec5SDimitry Andric  _Tp __a      = __z.real();
7270b57cec5SDimitry Andric  _Tp __b      = __z.imag();
7280b57cec5SDimitry Andric  _Tp __c      = __w.real();
7290b57cec5SDimitry Andric  _Tp __d      = __w.imag();
730bdd1243dSDimitry Andric  _Tp __logbw  = std::__constexpr_logb(std::__constexpr_fmax(std::__constexpr_fabs(__c), std::__constexpr_fabs(__d)));
731*cb14a3feSDimitry Andric  if (std::__constexpr_isfinite(__logbw)) {
7320b57cec5SDimitry Andric    __ilogbw = static_cast<int>(__logbw);
733bdd1243dSDimitry Andric    __c      = std::__constexpr_scalbn(__c, -__ilogbw);
734bdd1243dSDimitry Andric    __d      = std::__constexpr_scalbn(__d, -__ilogbw);
7350b57cec5SDimitry Andric  }
736bdd1243dSDimitry Andric
737bdd1243dSDimitry Andric  // Avoid floating point operations that are invalid during constant evaluation
738bdd1243dSDimitry Andric  if (__libcpp_is_constant_evaluated()) {
739bdd1243dSDimitry Andric    bool __z_zero = __a == _Tp(0) && __b == _Tp(0);
740bdd1243dSDimitry Andric    bool __w_zero = __c == _Tp(0) && __d == _Tp(0);
741bdd1243dSDimitry Andric    bool __z_inf  = std::__constexpr_isinf(__a) || std::__constexpr_isinf(__b);
742bdd1243dSDimitry Andric    bool __w_inf  = std::__constexpr_isinf(__c) || std::__constexpr_isinf(__d);
743*cb14a3feSDimitry Andric    bool __z_nan =
744*cb14a3feSDimitry Andric        !__z_inf && ((std::__constexpr_isnan(__a) && std::__constexpr_isnan(__b)) ||
745*cb14a3feSDimitry Andric                     (std::__constexpr_isnan(__a) && __b == _Tp(0)) || (__a == _Tp(0) && std::__constexpr_isnan(__b)));
746*cb14a3feSDimitry Andric    bool __w_nan =
747*cb14a3feSDimitry Andric        !__w_inf && ((std::__constexpr_isnan(__c) && std::__constexpr_isnan(__d)) ||
748*cb14a3feSDimitry Andric                     (std::__constexpr_isnan(__c) && __d == _Tp(0)) || (__c == _Tp(0) && std::__constexpr_isnan(__d)));
749bdd1243dSDimitry Andric    if ((__z_nan || __w_nan) || (__z_inf && __w_inf)) {
750bdd1243dSDimitry Andric      return complex<_Tp>(_Tp(numeric_limits<_Tp>::quiet_NaN()), _Tp(0));
751bdd1243dSDimitry Andric    }
752bdd1243dSDimitry Andric    bool __z_nonzero_nan = !__z_inf && !__z_nan && (std::__constexpr_isnan(__a) || std::__constexpr_isnan(__b));
753bdd1243dSDimitry Andric    bool __w_nonzero_nan = !__w_inf && !__w_nan && (std::__constexpr_isnan(__c) || std::__constexpr_isnan(__d));
754bdd1243dSDimitry Andric    if (__z_nonzero_nan || __w_nonzero_nan) {
755bdd1243dSDimitry Andric      if (__w_zero) {
756bdd1243dSDimitry Andric        return complex<_Tp>(_Tp(numeric_limits<_Tp>::infinity()), _Tp(numeric_limits<_Tp>::infinity()));
757bdd1243dSDimitry Andric      }
758bdd1243dSDimitry Andric      return complex<_Tp>(_Tp(numeric_limits<_Tp>::quiet_NaN()), _Tp(0));
759bdd1243dSDimitry Andric    }
760bdd1243dSDimitry Andric    if (__w_inf) {
761bdd1243dSDimitry Andric      return complex<_Tp>(_Tp(0), _Tp(0));
762bdd1243dSDimitry Andric    }
763bdd1243dSDimitry Andric    if (__z_inf) {
764bdd1243dSDimitry Andric      return complex<_Tp>(_Tp(numeric_limits<_Tp>::infinity()), _Tp(numeric_limits<_Tp>::infinity()));
765bdd1243dSDimitry Andric    }
766bdd1243dSDimitry Andric    if (__w_zero) {
767bdd1243dSDimitry Andric      if (__z_zero) {
768bdd1243dSDimitry Andric        return complex<_Tp>(_Tp(numeric_limits<_Tp>::quiet_NaN()), _Tp(0));
769bdd1243dSDimitry Andric      }
770bdd1243dSDimitry Andric      return complex<_Tp>(_Tp(numeric_limits<_Tp>::infinity()), _Tp(numeric_limits<_Tp>::infinity()));
771bdd1243dSDimitry Andric    }
772bdd1243dSDimitry Andric  }
773bdd1243dSDimitry Andric
7740b57cec5SDimitry Andric  _Tp __denom = __c * __c + __d * __d;
775bdd1243dSDimitry Andric  _Tp __x     = std::__constexpr_scalbn((__a * __c + __b * __d) / __denom, -__ilogbw);
776bdd1243dSDimitry Andric  _Tp __y     = std::__constexpr_scalbn((__b * __c - __a * __d) / __denom, -__ilogbw);
777*cb14a3feSDimitry Andric  if (std::__constexpr_isnan(__x) && std::__constexpr_isnan(__y)) {
778*cb14a3feSDimitry Andric    if ((__denom == _Tp(0)) && (!std::__constexpr_isnan(__a) || !std::__constexpr_isnan(__b))) {
779bdd1243dSDimitry Andric      __x = std::__constexpr_copysign(_Tp(INFINITY), __c) * __a;
780bdd1243dSDimitry Andric      __y = std::__constexpr_copysign(_Tp(INFINITY), __c) * __b;
781bdd1243dSDimitry Andric    } else if ((std::__constexpr_isinf(__a) || std::__constexpr_isinf(__b)) && std::__constexpr_isfinite(__c) &&
782bdd1243dSDimitry Andric               std::__constexpr_isfinite(__d)) {
783bdd1243dSDimitry Andric      __a = std::__constexpr_copysign(std::__constexpr_isinf(__a) ? _Tp(1) : _Tp(0), __a);
784bdd1243dSDimitry Andric      __b = std::__constexpr_copysign(std::__constexpr_isinf(__b) ? _Tp(1) : _Tp(0), __b);
7850b57cec5SDimitry Andric      __x = _Tp(INFINITY) * (__a * __c + __b * __d);
7860b57cec5SDimitry Andric      __y = _Tp(INFINITY) * (__b * __c - __a * __d);
787bdd1243dSDimitry Andric    } else if (std::__constexpr_isinf(__logbw) && __logbw > _Tp(0) && std::__constexpr_isfinite(__a) &&
788bdd1243dSDimitry Andric               std::__constexpr_isfinite(__b)) {
789bdd1243dSDimitry Andric      __c = std::__constexpr_copysign(std::__constexpr_isinf(__c) ? _Tp(1) : _Tp(0), __c);
790bdd1243dSDimitry Andric      __d = std::__constexpr_copysign(std::__constexpr_isinf(__d) ? _Tp(1) : _Tp(0), __d);
7910b57cec5SDimitry Andric      __x = _Tp(0) * (__a * __c + __b * __d);
7920b57cec5SDimitry Andric      __y = _Tp(0) * (__b * __c - __a * __d);
7930b57cec5SDimitry Andric    }
7940b57cec5SDimitry Andric  }
7950b57cec5SDimitry Andric  return complex<_Tp>(__x, __y);
7960b57cec5SDimitry Andric}
7970b57cec5SDimitry Andric
7980b57cec5SDimitry Andrictemplate <class _Tp>
799*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
800*cb14a3feSDimitry Andricoperator/(const complex<_Tp>& __x, const _Tp& __y) {
8010b57cec5SDimitry Andric  return complex<_Tp>(__x.real() / __y, __x.imag() / __y);
8020b57cec5SDimitry Andric}
8030b57cec5SDimitry Andric
8040b57cec5SDimitry Andrictemplate <class _Tp>
805*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
806*cb14a3feSDimitry Andricoperator/(const _Tp& __x, const complex<_Tp>& __y) {
8070b57cec5SDimitry Andric  complex<_Tp> __t(__x);
8080b57cec5SDimitry Andric  __t /= __y;
8090b57cec5SDimitry Andric  return __t;
8100b57cec5SDimitry Andric}
8110b57cec5SDimitry Andric
8120b57cec5SDimitry Andrictemplate <class _Tp>
813*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> operator+(const complex<_Tp>& __x) {
8140b57cec5SDimitry Andric  return __x;
8150b57cec5SDimitry Andric}
8160b57cec5SDimitry Andric
8170b57cec5SDimitry Andrictemplate <class _Tp>
818*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> operator-(const complex<_Tp>& __x) {
8190b57cec5SDimitry Andric  return complex<_Tp>(-__x.real(), -__x.imag());
8200b57cec5SDimitry Andric}
8210b57cec5SDimitry Andric
8220b57cec5SDimitry Andrictemplate <class _Tp>
823*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool
824*cb14a3feSDimitry Andricoperator==(const complex<_Tp>& __x, const complex<_Tp>& __y) {
8250b57cec5SDimitry Andric  return __x.real() == __y.real() && __x.imag() == __y.imag();
8260b57cec5SDimitry Andric}
8270b57cec5SDimitry Andric
8280b57cec5SDimitry Andrictemplate <class _Tp>
829*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool operator==(const complex<_Tp>& __x, const _Tp& __y) {
8300b57cec5SDimitry Andric  return __x.real() == __y && __x.imag() == 0;
8310b57cec5SDimitry Andric}
8320b57cec5SDimitry Andric
83306c3fb27SDimitry Andric#if _LIBCPP_STD_VER <= 17
83406c3fb27SDimitry Andric
8350b57cec5SDimitry Andrictemplate <class _Tp>
836*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool operator==(const _Tp& __x, const complex<_Tp>& __y) {
8370b57cec5SDimitry Andric  return __x == __y.real() && 0 == __y.imag();
8380b57cec5SDimitry Andric}
8390b57cec5SDimitry Andric
8400b57cec5SDimitry Andrictemplate <class _Tp>
841*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool
842*cb14a3feSDimitry Andricoperator!=(const complex<_Tp>& __x, const complex<_Tp>& __y) {
8430b57cec5SDimitry Andric  return !(__x == __y);
8440b57cec5SDimitry Andric}
8450b57cec5SDimitry Andric
8460b57cec5SDimitry Andrictemplate <class _Tp>
847*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool operator!=(const complex<_Tp>& __x, const _Tp& __y) {
8480b57cec5SDimitry Andric  return !(__x == __y);
8490b57cec5SDimitry Andric}
8500b57cec5SDimitry Andric
8510b57cec5SDimitry Andrictemplate <class _Tp>
852*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool operator!=(const _Tp& __x, const complex<_Tp>& __y) {
8530b57cec5SDimitry Andric  return !(__x == __y);
8540b57cec5SDimitry Andric}
8550b57cec5SDimitry Andric
85606c3fb27SDimitry Andric#endif
85706c3fb27SDimitry Andric
8580b57cec5SDimitry Andric// 26.3.7 values:
8590b57cec5SDimitry Andric
860*cb14a3feSDimitry Andrictemplate <class _Tp, bool = is_integral<_Tp>::value, bool = is_floating_point<_Tp>::value >
8610b57cec5SDimitry Andricstruct __libcpp_complex_overload_traits {};
8620b57cec5SDimitry Andric
8630b57cec5SDimitry Andric// Integral Types
8640b57cec5SDimitry Andrictemplate <class _Tp>
865*cb14a3feSDimitry Andricstruct __libcpp_complex_overload_traits<_Tp, true, false> {
8660b57cec5SDimitry Andric  typedef double _ValueType;
8670b57cec5SDimitry Andric  typedef complex<double> _ComplexType;
8680b57cec5SDimitry Andric};
8690b57cec5SDimitry Andric
8700b57cec5SDimitry Andric// Floating point types
8710b57cec5SDimitry Andrictemplate <class _Tp>
872*cb14a3feSDimitry Andricstruct __libcpp_complex_overload_traits<_Tp, false, true> {
8730b57cec5SDimitry Andric  typedef _Tp _ValueType;
8740b57cec5SDimitry Andric  typedef complex<_Tp> _ComplexType;
8750b57cec5SDimitry Andric};
8760b57cec5SDimitry Andric
8770b57cec5SDimitry Andric// real
8780b57cec5SDimitry Andric
8790b57cec5SDimitry Andrictemplate <class _Tp>
880*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp real(const complex<_Tp>& __c) {
8810b57cec5SDimitry Andric  return __c.real();
8820b57cec5SDimitry Andric}
8830b57cec5SDimitry Andric
8840b57cec5SDimitry Andrictemplate <class _Tp>
885*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 typename __libcpp_complex_overload_traits<_Tp>::_ValueType
886*cb14a3feSDimitry Andricreal(_Tp __re) {
8870b57cec5SDimitry Andric  return __re;
8880b57cec5SDimitry Andric}
8890b57cec5SDimitry Andric
8900b57cec5SDimitry Andric// imag
8910b57cec5SDimitry Andric
8920b57cec5SDimitry Andrictemplate <class _Tp>
893*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp imag(const complex<_Tp>& __c) {
8940b57cec5SDimitry Andric  return __c.imag();
8950b57cec5SDimitry Andric}
8960b57cec5SDimitry Andric
8970b57cec5SDimitry Andrictemplate <class _Tp>
898*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 typename __libcpp_complex_overload_traits<_Tp>::_ValueType
899*cb14a3feSDimitry Andricimag(_Tp) {
9000b57cec5SDimitry Andric  return 0;
9010b57cec5SDimitry Andric}
9020b57cec5SDimitry Andric
9030b57cec5SDimitry Andric// abs
9040b57cec5SDimitry Andric
9050b57cec5SDimitry Andrictemplate <class _Tp>
906*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI _Tp abs(const complex<_Tp>& __c) {
907bdd1243dSDimitry Andric  return std::hypot(__c.real(), __c.imag());
9080b57cec5SDimitry Andric}
9090b57cec5SDimitry Andric
9100b57cec5SDimitry Andric// arg
9110b57cec5SDimitry Andric
9120b57cec5SDimitry Andrictemplate <class _Tp>
913*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI _Tp arg(const complex<_Tp>& __c) {
914bdd1243dSDimitry Andric  return std::atan2(__c.imag(), __c.real());
9150b57cec5SDimitry Andric}
9160b57cec5SDimitry Andric
9175f757f3fSDimitry Andrictemplate <class _Tp, __enable_if_t<is_same<_Tp, long double>::value, int> = 0>
918*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI long double arg(_Tp __re) {
919bdd1243dSDimitry Andric  return std::atan2l(0.L, __re);
9200b57cec5SDimitry Andric}
9210b57cec5SDimitry Andric
9225f757f3fSDimitry Andrictemplate <class _Tp, __enable_if_t<is_integral<_Tp>::value || is_same<_Tp, double>::value, int> = 0>
923*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI double arg(_Tp __re) {
924bdd1243dSDimitry Andric  return std::atan2(0., __re);
9250b57cec5SDimitry Andric}
9260b57cec5SDimitry Andric
9275f757f3fSDimitry Andrictemplate <class _Tp, __enable_if_t<is_same<_Tp, float>::value, int> = 0>
928*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI float arg(_Tp __re) {
929bdd1243dSDimitry Andric  return std::atan2f(0.F, __re);
9300b57cec5SDimitry Andric}
9310b57cec5SDimitry Andric
9320b57cec5SDimitry Andric// norm
9330b57cec5SDimitry Andric
9340b57cec5SDimitry Andrictemplate <class _Tp>
935*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp norm(const complex<_Tp>& __c) {
936bdd1243dSDimitry Andric  if (std::__constexpr_isinf(__c.real()))
937bdd1243dSDimitry Andric    return std::abs(__c.real());
938bdd1243dSDimitry Andric  if (std::__constexpr_isinf(__c.imag()))
939bdd1243dSDimitry Andric    return std::abs(__c.imag());
9400b57cec5SDimitry Andric  return __c.real() * __c.real() + __c.imag() * __c.imag();
9410b57cec5SDimitry Andric}
9420b57cec5SDimitry Andric
9430b57cec5SDimitry Andrictemplate <class _Tp>
944*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 typename __libcpp_complex_overload_traits<_Tp>::_ValueType
945*cb14a3feSDimitry Andricnorm(_Tp __re) {
9460b57cec5SDimitry Andric  typedef typename __libcpp_complex_overload_traits<_Tp>::_ValueType _ValueType;
9470b57cec5SDimitry Andric  return static_cast<_ValueType>(__re) * __re;
9480b57cec5SDimitry Andric}
9490b57cec5SDimitry Andric
9500b57cec5SDimitry Andric// conj
9510b57cec5SDimitry Andric
9520b57cec5SDimitry Andrictemplate <class _Tp>
953*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> conj(const complex<_Tp>& __c) {
9540b57cec5SDimitry Andric  return complex<_Tp>(__c.real(), -__c.imag());
9550b57cec5SDimitry Andric}
9560b57cec5SDimitry Andric
9570b57cec5SDimitry Andrictemplate <class _Tp>
958*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 typename __libcpp_complex_overload_traits<_Tp>::_ComplexType
959*cb14a3feSDimitry Andricconj(_Tp __re) {
9600b57cec5SDimitry Andric  typedef typename __libcpp_complex_overload_traits<_Tp>::_ComplexType _ComplexType;
9610b57cec5SDimitry Andric  return _ComplexType(__re);
9620b57cec5SDimitry Andric}
9630b57cec5SDimitry Andric
9640b57cec5SDimitry Andric// proj
9650b57cec5SDimitry Andric
9660b57cec5SDimitry Andrictemplate <class _Tp>
967*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI complex<_Tp> proj(const complex<_Tp>& __c) {
968e8d8bef9SDimitry Andric  complex<_Tp> __r = __c;
969bdd1243dSDimitry Andric  if (std::__constexpr_isinf(__c.real()) || std::__constexpr_isinf(__c.imag()))
970bdd1243dSDimitry Andric    __r = complex<_Tp>(INFINITY, std::copysign(_Tp(0), __c.imag()));
9710b57cec5SDimitry Andric  return __r;
9720b57cec5SDimitry Andric}
9730b57cec5SDimitry Andric
9745f757f3fSDimitry Andrictemplate <class _Tp, __enable_if_t<is_floating_point<_Tp>::value, int> = 0>
975*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI typename __libcpp_complex_overload_traits<_Tp>::_ComplexType proj(_Tp __re) {
976bdd1243dSDimitry Andric  if (std::__constexpr_isinf(__re))
977bdd1243dSDimitry Andric    __re = std::abs(__re);
9780b57cec5SDimitry Andric  return complex<_Tp>(__re);
9790b57cec5SDimitry Andric}
9800b57cec5SDimitry Andric
9815f757f3fSDimitry Andrictemplate <class _Tp, __enable_if_t<is_integral<_Tp>::value, int> = 0>
982*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI typename __libcpp_complex_overload_traits<_Tp>::_ComplexType proj(_Tp __re) {
9830b57cec5SDimitry Andric  typedef typename __libcpp_complex_overload_traits<_Tp>::_ComplexType _ComplexType;
9840b57cec5SDimitry Andric  return _ComplexType(__re);
9850b57cec5SDimitry Andric}
9860b57cec5SDimitry Andric
9870b57cec5SDimitry Andric// polar
9880b57cec5SDimitry Andric
9890b57cec5SDimitry Andrictemplate <class _Tp>
990*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI complex<_Tp> polar(const _Tp& __rho, const _Tp& __theta = _Tp()) {
991bdd1243dSDimitry Andric  if (std::__constexpr_isnan(__rho) || std::signbit(__rho))
9920b57cec5SDimitry Andric    return complex<_Tp>(_Tp(NAN), _Tp(NAN));
993*cb14a3feSDimitry Andric  if (std::__constexpr_isnan(__theta)) {
994bdd1243dSDimitry Andric    if (std::__constexpr_isinf(__rho))
9950b57cec5SDimitry Andric      return complex<_Tp>(__rho, __theta);
9960b57cec5SDimitry Andric    return complex<_Tp>(__theta, __theta);
9970b57cec5SDimitry Andric  }
998*cb14a3feSDimitry Andric  if (std::__constexpr_isinf(__theta)) {
999bdd1243dSDimitry Andric    if (std::__constexpr_isinf(__rho))
10000b57cec5SDimitry Andric      return complex<_Tp>(__rho, _Tp(NAN));
10010b57cec5SDimitry Andric    return complex<_Tp>(_Tp(NAN), _Tp(NAN));
10020b57cec5SDimitry Andric  }
1003bdd1243dSDimitry Andric  _Tp __x = __rho * std::cos(__theta);
1004bdd1243dSDimitry Andric  if (std::__constexpr_isnan(__x))
10050b57cec5SDimitry Andric    __x = 0;
1006bdd1243dSDimitry Andric  _Tp __y = __rho * std::sin(__theta);
1007bdd1243dSDimitry Andric  if (std::__constexpr_isnan(__y))
10080b57cec5SDimitry Andric    __y = 0;
10090b57cec5SDimitry Andric  return complex<_Tp>(__x, __y);
10100b57cec5SDimitry Andric}
10110b57cec5SDimitry Andric
10120b57cec5SDimitry Andric// log
10130b57cec5SDimitry Andric
10140b57cec5SDimitry Andrictemplate <class _Tp>
1015*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI complex<_Tp> log(const complex<_Tp>& __x) {
1016bdd1243dSDimitry Andric  return complex<_Tp>(std::log(std::abs(__x)), std::arg(__x));
10170b57cec5SDimitry Andric}
10180b57cec5SDimitry Andric
10190b57cec5SDimitry Andric// log10
10200b57cec5SDimitry Andric
10210b57cec5SDimitry Andrictemplate <class _Tp>
1022*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI complex<_Tp> log10(const complex<_Tp>& __x) {
1023bdd1243dSDimitry Andric  return std::log(__x) / std::log(_Tp(10));
10240b57cec5SDimitry Andric}
10250b57cec5SDimitry Andric
10260b57cec5SDimitry Andric// sqrt
10270b57cec5SDimitry Andric
10280b57cec5SDimitry Andrictemplate <class _Tp>
1029*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI complex<_Tp> sqrt(const complex<_Tp>& __x) {
1030bdd1243dSDimitry Andric  if (std::__constexpr_isinf(__x.imag()))
10310b57cec5SDimitry Andric    return complex<_Tp>(_Tp(INFINITY), __x.imag());
1032*cb14a3feSDimitry Andric  if (std::__constexpr_isinf(__x.real())) {
10330b57cec5SDimitry Andric    if (__x.real() > _Tp(0))
1034*cb14a3feSDimitry Andric      return complex<_Tp>(
1035*cb14a3feSDimitry Andric          __x.real(), std::__constexpr_isnan(__x.imag()) ? __x.imag() : std::copysign(_Tp(0), __x.imag()));
1036*cb14a3feSDimitry Andric    return complex<_Tp>(
1037*cb14a3feSDimitry Andric        std::__constexpr_isnan(__x.imag()) ? __x.imag() : _Tp(0), std::copysign(__x.real(), __x.imag()));
10380b57cec5SDimitry Andric  }
1039bdd1243dSDimitry Andric  return std::polar(std::sqrt(std::abs(__x)), std::arg(__x) / _Tp(2));
10400b57cec5SDimitry Andric}
10410b57cec5SDimitry Andric
10420b57cec5SDimitry Andric// exp
10430b57cec5SDimitry Andric
10440b57cec5SDimitry Andrictemplate <class _Tp>
1045*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI complex<_Tp> exp(const complex<_Tp>& __x) {
10460b57cec5SDimitry Andric  _Tp __i = __x.imag();
1047349cc55cSDimitry Andric  if (__i == 0) {
1048bdd1243dSDimitry Andric    return complex<_Tp>(std::exp(__x.real()), std::copysign(_Tp(0), __x.imag()));
1049349cc55cSDimitry Andric  }
1050*cb14a3feSDimitry Andric  if (std::__constexpr_isinf(__x.real())) {
1051*cb14a3feSDimitry Andric    if (__x.real() < _Tp(0)) {
1052bdd1243dSDimitry Andric      if (!std::__constexpr_isfinite(__i))
10530b57cec5SDimitry Andric        __i = _Tp(1);
1054*cb14a3feSDimitry Andric    } else if (__i == 0 || !std::__constexpr_isfinite(__i)) {
1055bdd1243dSDimitry Andric      if (std::__constexpr_isinf(__i))
10560b57cec5SDimitry Andric        __i = _Tp(NAN);
10570b57cec5SDimitry Andric      return complex<_Tp>(__x.real(), __i);
10580b57cec5SDimitry Andric    }
10590b57cec5SDimitry Andric  }
1060bdd1243dSDimitry Andric  _Tp __e = std::exp(__x.real());
1061bdd1243dSDimitry Andric  return complex<_Tp>(__e * std::cos(__i), __e * std::sin(__i));
10620b57cec5SDimitry Andric}
10630b57cec5SDimitry Andric
10640b57cec5SDimitry Andric// pow
10650b57cec5SDimitry Andric
10660b57cec5SDimitry Andrictemplate <class _Tp>
1067*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI complex<_Tp> pow(const complex<_Tp>& __x, const complex<_Tp>& __y) {
1068bdd1243dSDimitry Andric  return std::exp(__y * std::log(__x));
10690b57cec5SDimitry Andric}
10700b57cec5SDimitry Andric
10710b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
1072*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI complex<typename __promote<_Tp, _Up>::type>
1073*cb14a3feSDimitry Andricpow(const complex<_Tp>& __x, const complex<_Up>& __y) {
10740b57cec5SDimitry Andric  typedef complex<typename __promote<_Tp, _Up>::type> result_type;
10755f757f3fSDimitry Andric  return std::pow(result_type(__x), result_type(__y));
10760b57cec5SDimitry Andric}
10770b57cec5SDimitry Andric
10785f757f3fSDimitry Andrictemplate <class _Tp, class _Up, __enable_if_t<is_arithmetic<_Up>::value, int> = 0>
1079*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI complex<typename __promote<_Tp, _Up>::type> pow(const complex<_Tp>& __x, const _Up& __y) {
10800b57cec5SDimitry Andric  typedef complex<typename __promote<_Tp, _Up>::type> result_type;
10815f757f3fSDimitry Andric  return std::pow(result_type(__x), result_type(__y));
10820b57cec5SDimitry Andric}
10830b57cec5SDimitry Andric
10845f757f3fSDimitry Andrictemplate <class _Tp, class _Up, __enable_if_t<is_arithmetic<_Tp>::value, int> = 0>
1085*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI complex<typename __promote<_Tp, _Up>::type> pow(const _Tp& __x, const complex<_Up>& __y) {
10860b57cec5SDimitry Andric  typedef complex<typename __promote<_Tp, _Up>::type> result_type;
10875f757f3fSDimitry Andric  return std::pow(result_type(__x), result_type(__y));
10880b57cec5SDimitry Andric}
10890b57cec5SDimitry Andric
10900b57cec5SDimitry Andric// __sqr, computes pow(x, 2)
10910b57cec5SDimitry Andric
10920b57cec5SDimitry Andrictemplate <class _Tp>
1093*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI complex<_Tp> __sqr(const complex<_Tp>& __x) {
1094*cb14a3feSDimitry Andric  return complex<_Tp>((__x.real() - __x.imag()) * (__x.real() + __x.imag()), _Tp(2) * __x.real() * __x.imag());
10950b57cec5SDimitry Andric}
10960b57cec5SDimitry Andric
10970b57cec5SDimitry Andric// asinh
10980b57cec5SDimitry Andric
10990b57cec5SDimitry Andrictemplate <class _Tp>
1100*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI complex<_Tp> asinh(const complex<_Tp>& __x) {
11010b57cec5SDimitry Andric  const _Tp __pi(atan2(+0., -0.));
1102*cb14a3feSDimitry Andric  if (std::__constexpr_isinf(__x.real())) {
1103bdd1243dSDimitry Andric    if (std::__constexpr_isnan(__x.imag()))
11040b57cec5SDimitry Andric      return __x;
1105bdd1243dSDimitry Andric    if (std::__constexpr_isinf(__x.imag()))
1106bdd1243dSDimitry Andric      return complex<_Tp>(__x.real(), std::copysign(__pi * _Tp(0.25), __x.imag()));
1107bdd1243dSDimitry Andric    return complex<_Tp>(__x.real(), std::copysign(_Tp(0), __x.imag()));
11080b57cec5SDimitry Andric  }
1109*cb14a3feSDimitry Andric  if (std::__constexpr_isnan(__x.real())) {
1110bdd1243dSDimitry Andric    if (std::__constexpr_isinf(__x.imag()))
11110b57cec5SDimitry Andric      return complex<_Tp>(__x.imag(), __x.real());
11120b57cec5SDimitry Andric    if (__x.imag() == 0)
11130b57cec5SDimitry Andric      return __x;
11140b57cec5SDimitry Andric    return complex<_Tp>(__x.real(), __x.real());
11150b57cec5SDimitry Andric  }
1116bdd1243dSDimitry Andric  if (std::__constexpr_isinf(__x.imag()))
1117bdd1243dSDimitry Andric    return complex<_Tp>(std::copysign(__x.imag(), __x.real()), std::copysign(__pi / _Tp(2), __x.imag()));
1118bdd1243dSDimitry Andric  complex<_Tp> __z = std::log(__x + std::sqrt(std::__sqr(__x) + _Tp(1)));
1119bdd1243dSDimitry Andric  return complex<_Tp>(std::copysign(__z.real(), __x.real()), std::copysign(__z.imag(), __x.imag()));
11200b57cec5SDimitry Andric}
11210b57cec5SDimitry Andric
11220b57cec5SDimitry Andric// acosh
11230b57cec5SDimitry Andric
11240b57cec5SDimitry Andrictemplate <class _Tp>
1125*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI complex<_Tp> acosh(const complex<_Tp>& __x) {
11260b57cec5SDimitry Andric  const _Tp __pi(atan2(+0., -0.));
1127*cb14a3feSDimitry Andric  if (std::__constexpr_isinf(__x.real())) {
1128bdd1243dSDimitry Andric    if (std::__constexpr_isnan(__x.imag()))
1129bdd1243dSDimitry Andric      return complex<_Tp>(std::abs(__x.real()), __x.imag());
1130*cb14a3feSDimitry Andric    if (std::__constexpr_isinf(__x.imag())) {
11310b57cec5SDimitry Andric      if (__x.real() > 0)
1132bdd1243dSDimitry Andric        return complex<_Tp>(__x.real(), std::copysign(__pi * _Tp(0.25), __x.imag()));
11330b57cec5SDimitry Andric      else
1134bdd1243dSDimitry Andric        return complex<_Tp>(-__x.real(), std::copysign(__pi * _Tp(0.75), __x.imag()));
11350b57cec5SDimitry Andric    }
11360b57cec5SDimitry Andric    if (__x.real() < 0)
1137bdd1243dSDimitry Andric      return complex<_Tp>(-__x.real(), std::copysign(__pi, __x.imag()));
1138bdd1243dSDimitry Andric    return complex<_Tp>(__x.real(), std::copysign(_Tp(0), __x.imag()));
11390b57cec5SDimitry Andric  }
1140*cb14a3feSDimitry Andric  if (std::__constexpr_isnan(__x.real())) {
1141bdd1243dSDimitry Andric    if (std::__constexpr_isinf(__x.imag()))
1142bdd1243dSDimitry Andric      return complex<_Tp>(std::abs(__x.imag()), __x.real());
11430b57cec5SDimitry Andric    return complex<_Tp>(__x.real(), __x.real());
11440b57cec5SDimitry Andric  }
1145bdd1243dSDimitry Andric  if (std::__constexpr_isinf(__x.imag()))
1146bdd1243dSDimitry Andric    return complex<_Tp>(std::abs(__x.imag()), std::copysign(__pi / _Tp(2), __x.imag()));
1147bdd1243dSDimitry Andric  complex<_Tp> __z = std::log(__x + std::sqrt(std::__sqr(__x) - _Tp(1)));
1148bdd1243dSDimitry Andric  return complex<_Tp>(std::copysign(__z.real(), _Tp(0)), std::copysign(__z.imag(), __x.imag()));
11490b57cec5SDimitry Andric}
11500b57cec5SDimitry Andric
11510b57cec5SDimitry Andric// atanh
11520b57cec5SDimitry Andric
11530b57cec5SDimitry Andrictemplate <class _Tp>
1154*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI complex<_Tp> atanh(const complex<_Tp>& __x) {
11550b57cec5SDimitry Andric  const _Tp __pi(atan2(+0., -0.));
1156*cb14a3feSDimitry Andric  if (std::__constexpr_isinf(__x.imag())) {
1157bdd1243dSDimitry Andric    return complex<_Tp>(std::copysign(_Tp(0), __x.real()), std::copysign(__pi / _Tp(2), __x.imag()));
11580b57cec5SDimitry Andric  }
1159*cb14a3feSDimitry Andric  if (std::__constexpr_isnan(__x.imag())) {
1160bdd1243dSDimitry Andric    if (std::__constexpr_isinf(__x.real()) || __x.real() == 0)
1161bdd1243dSDimitry Andric      return complex<_Tp>(std::copysign(_Tp(0), __x.real()), __x.imag());
11620b57cec5SDimitry Andric    return complex<_Tp>(__x.imag(), __x.imag());
11630b57cec5SDimitry Andric  }
1164*cb14a3feSDimitry Andric  if (std::__constexpr_isnan(__x.real())) {
11650b57cec5SDimitry Andric    return complex<_Tp>(__x.real(), __x.real());
11660b57cec5SDimitry Andric  }
1167*cb14a3feSDimitry Andric  if (std::__constexpr_isinf(__x.real())) {
1168bdd1243dSDimitry Andric    return complex<_Tp>(std::copysign(_Tp(0), __x.real()), std::copysign(__pi / _Tp(2), __x.imag()));
11690b57cec5SDimitry Andric  }
1170*cb14a3feSDimitry Andric  if (std::abs(__x.real()) == _Tp(1) && __x.imag() == _Tp(0)) {
1171bdd1243dSDimitry Andric    return complex<_Tp>(std::copysign(_Tp(INFINITY), __x.real()), std::copysign(_Tp(0), __x.imag()));
11720b57cec5SDimitry Andric  }
1173bdd1243dSDimitry Andric  complex<_Tp> __z = std::log((_Tp(1) + __x) / (_Tp(1) - __x)) / _Tp(2);
1174bdd1243dSDimitry Andric  return complex<_Tp>(std::copysign(__z.real(), __x.real()), std::copysign(__z.imag(), __x.imag()));
11750b57cec5SDimitry Andric}
11760b57cec5SDimitry Andric
11770b57cec5SDimitry Andric// sinh
11780b57cec5SDimitry Andric
11790b57cec5SDimitry Andrictemplate <class _Tp>
1180*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI complex<_Tp> sinh(const complex<_Tp>& __x) {
1181bdd1243dSDimitry Andric  if (std::__constexpr_isinf(__x.real()) && !std::__constexpr_isfinite(__x.imag()))
11820b57cec5SDimitry Andric    return complex<_Tp>(__x.real(), _Tp(NAN));
1183bdd1243dSDimitry Andric  if (__x.real() == 0 && !std::__constexpr_isfinite(__x.imag()))
11840b57cec5SDimitry Andric    return complex<_Tp>(__x.real(), _Tp(NAN));
1185bdd1243dSDimitry Andric  if (__x.imag() == 0 && !std::__constexpr_isfinite(__x.real()))
11860b57cec5SDimitry Andric    return __x;
1187bdd1243dSDimitry Andric  return complex<_Tp>(std::sinh(__x.real()) * std::cos(__x.imag()), std::cosh(__x.real()) * std::sin(__x.imag()));
11880b57cec5SDimitry Andric}
11890b57cec5SDimitry Andric
11900b57cec5SDimitry Andric// cosh
11910b57cec5SDimitry Andric
11920b57cec5SDimitry Andrictemplate <class _Tp>
1193*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI complex<_Tp> cosh(const complex<_Tp>& __x) {
1194bdd1243dSDimitry Andric  if (std::__constexpr_isinf(__x.real()) && !std::__constexpr_isfinite(__x.imag()))
1195bdd1243dSDimitry Andric    return complex<_Tp>(std::abs(__x.real()), _Tp(NAN));
1196bdd1243dSDimitry Andric  if (__x.real() == 0 && !std::__constexpr_isfinite(__x.imag()))
11970b57cec5SDimitry Andric    return complex<_Tp>(_Tp(NAN), __x.real());
11980b57cec5SDimitry Andric  if (__x.real() == 0 && __x.imag() == 0)
11990b57cec5SDimitry Andric    return complex<_Tp>(_Tp(1), __x.imag());
1200bdd1243dSDimitry Andric  if (__x.imag() == 0 && !std::__constexpr_isfinite(__x.real()))
1201bdd1243dSDimitry Andric    return complex<_Tp>(std::abs(__x.real()), __x.imag());
1202bdd1243dSDimitry Andric  return complex<_Tp>(std::cosh(__x.real()) * std::cos(__x.imag()), std::sinh(__x.real()) * std::sin(__x.imag()));
12030b57cec5SDimitry Andric}
12040b57cec5SDimitry Andric
12050b57cec5SDimitry Andric// tanh
12060b57cec5SDimitry Andric
12070b57cec5SDimitry Andrictemplate <class _Tp>
1208*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI complex<_Tp> tanh(const complex<_Tp>& __x) {
1209*cb14a3feSDimitry Andric  if (std::__constexpr_isinf(__x.real())) {
1210bdd1243dSDimitry Andric    if (!std::__constexpr_isfinite(__x.imag()))
1211bdd1243dSDimitry Andric      return complex<_Tp>(std::copysign(_Tp(1), __x.real()), _Tp(0));
1212bdd1243dSDimitry Andric    return complex<_Tp>(std::copysign(_Tp(1), __x.real()), std::copysign(_Tp(0), std::sin(_Tp(2) * __x.imag())));
12130b57cec5SDimitry Andric  }
1214bdd1243dSDimitry Andric  if (std::__constexpr_isnan(__x.real()) && __x.imag() == 0)
12150b57cec5SDimitry Andric    return __x;
12160b57cec5SDimitry Andric  _Tp __2r(_Tp(2) * __x.real());
12170b57cec5SDimitry Andric  _Tp __2i(_Tp(2) * __x.imag());
1218bdd1243dSDimitry Andric  _Tp __d(std::cosh(__2r) + std::cos(__2i));
1219bdd1243dSDimitry Andric  _Tp __2rsh(std::sinh(__2r));
1220bdd1243dSDimitry Andric  if (std::__constexpr_isinf(__2rsh) && std::__constexpr_isinf(__d))
1221*cb14a3feSDimitry Andric    return complex<_Tp>(__2rsh > _Tp(0) ? _Tp(1) : _Tp(-1), __2i > _Tp(0) ? _Tp(0) : _Tp(-0.));
1222bdd1243dSDimitry Andric  return complex<_Tp>(__2rsh / __d, std::sin(__2i) / __d);
12230b57cec5SDimitry Andric}
12240b57cec5SDimitry Andric
12250b57cec5SDimitry Andric// asin
12260b57cec5SDimitry Andric
12270b57cec5SDimitry Andrictemplate <class _Tp>
1228*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI complex<_Tp> asin(const complex<_Tp>& __x) {
1229bdd1243dSDimitry Andric  complex<_Tp> __z = std::asinh(complex<_Tp>(-__x.imag(), __x.real()));
12300b57cec5SDimitry Andric  return complex<_Tp>(__z.imag(), -__z.real());
12310b57cec5SDimitry Andric}
12320b57cec5SDimitry Andric
12330b57cec5SDimitry Andric// acos
12340b57cec5SDimitry Andric
12350b57cec5SDimitry Andrictemplate <class _Tp>
1236*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI complex<_Tp> acos(const complex<_Tp>& __x) {
12370b57cec5SDimitry Andric  const _Tp __pi(atan2(+0., -0.));
1238*cb14a3feSDimitry Andric  if (std::__constexpr_isinf(__x.real())) {
1239bdd1243dSDimitry Andric    if (std::__constexpr_isnan(__x.imag()))
12400b57cec5SDimitry Andric      return complex<_Tp>(__x.imag(), __x.real());
1241*cb14a3feSDimitry Andric    if (std::__constexpr_isinf(__x.imag())) {
12420b57cec5SDimitry Andric      if (__x.real() < _Tp(0))
12430b57cec5SDimitry Andric        return complex<_Tp>(_Tp(0.75) * __pi, -__x.imag());
12440b57cec5SDimitry Andric      return complex<_Tp>(_Tp(0.25) * __pi, -__x.imag());
12450b57cec5SDimitry Andric    }
12460b57cec5SDimitry Andric    if (__x.real() < _Tp(0))
1247bdd1243dSDimitry Andric      return complex<_Tp>(__pi, std::signbit(__x.imag()) ? -__x.real() : __x.real());
1248bdd1243dSDimitry Andric    return complex<_Tp>(_Tp(0), std::signbit(__x.imag()) ? __x.real() : -__x.real());
12490b57cec5SDimitry Andric  }
1250*cb14a3feSDimitry Andric  if (std::__constexpr_isnan(__x.real())) {
1251bdd1243dSDimitry Andric    if (std::__constexpr_isinf(__x.imag()))
12520b57cec5SDimitry Andric      return complex<_Tp>(__x.real(), -__x.imag());
12530b57cec5SDimitry Andric    return complex<_Tp>(__x.real(), __x.real());
12540b57cec5SDimitry Andric  }
1255bdd1243dSDimitry Andric  if (std::__constexpr_isinf(__x.imag()))
12560b57cec5SDimitry Andric    return complex<_Tp>(__pi / _Tp(2), -__x.imag());
1257bdd1243dSDimitry Andric  if (__x.real() == 0 && (__x.imag() == 0 || std::isnan(__x.imag())))
12580b57cec5SDimitry Andric    return complex<_Tp>(__pi / _Tp(2), -__x.imag());
1259bdd1243dSDimitry Andric  complex<_Tp> __z = std::log(__x + std::sqrt(std::__sqr(__x) - _Tp(1)));
1260bdd1243dSDimitry Andric  if (std::signbit(__x.imag()))
1261bdd1243dSDimitry Andric    return complex<_Tp>(std::abs(__z.imag()), std::abs(__z.real()));
1262bdd1243dSDimitry Andric  return complex<_Tp>(std::abs(__z.imag()), -std::abs(__z.real()));
12630b57cec5SDimitry Andric}
12640b57cec5SDimitry Andric
12650b57cec5SDimitry Andric// atan
12660b57cec5SDimitry Andric
12670b57cec5SDimitry Andrictemplate <class _Tp>
1268*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI complex<_Tp> atan(const complex<_Tp>& __x) {
1269bdd1243dSDimitry Andric  complex<_Tp> __z = std::atanh(complex<_Tp>(-__x.imag(), __x.real()));
12700b57cec5SDimitry Andric  return complex<_Tp>(__z.imag(), -__z.real());
12710b57cec5SDimitry Andric}
12720b57cec5SDimitry Andric
12730b57cec5SDimitry Andric// sin
12740b57cec5SDimitry Andric
12750b57cec5SDimitry Andrictemplate <class _Tp>
1276*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI complex<_Tp> sin(const complex<_Tp>& __x) {
1277bdd1243dSDimitry Andric  complex<_Tp> __z = std::sinh(complex<_Tp>(-__x.imag(), __x.real()));
12780b57cec5SDimitry Andric  return complex<_Tp>(__z.imag(), -__z.real());
12790b57cec5SDimitry Andric}
12800b57cec5SDimitry Andric
12810b57cec5SDimitry Andric// cos
12820b57cec5SDimitry Andric
12830b57cec5SDimitry Andrictemplate <class _Tp>
1284*cb14a3feSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI complex<_Tp> cos(const complex<_Tp>& __x) {
1285bdd1243dSDimitry Andric  return std::cosh(complex<_Tp>(-__x.imag(), __x.real()));
12860b57cec5SDimitry Andric}
12870b57cec5SDimitry Andric
12880b57cec5SDimitry Andric// tan
12890b57cec5SDimitry Andric
12900b57cec5SDimitry Andrictemplate <class _Tp>
1291*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI complex<_Tp> tan(const complex<_Tp>& __x) {
1292bdd1243dSDimitry Andric  complex<_Tp> __z = std::tanh(complex<_Tp>(-__x.imag(), __x.real()));
12930b57cec5SDimitry Andric  return complex<_Tp>(__z.imag(), -__z.real());
12940b57cec5SDimitry Andric}
12950b57cec5SDimitry Andric
1296bdd1243dSDimitry Andric#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
12970b57cec5SDimitry Andrictemplate <class _Tp, class _CharT, class _Traits>
1298bdd1243dSDimitry Andric_LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>&
1299*cb14a3feSDimitry Andricoperator>>(basic_istream<_CharT, _Traits>& __is, complex<_Tp>& __x) {
1300*cb14a3feSDimitry Andric  if (__is.good()) {
1301bdd1243dSDimitry Andric    std::ws(__is);
1302*cb14a3feSDimitry Andric    if (__is.peek() == _CharT('(')) {
13030b57cec5SDimitry Andric      __is.get();
13040b57cec5SDimitry Andric      _Tp __r;
13050b57cec5SDimitry Andric      __is >> __r;
1306*cb14a3feSDimitry Andric      if (!__is.fail()) {
1307bdd1243dSDimitry Andric        std::ws(__is);
13080b57cec5SDimitry Andric        _CharT __c = __is.peek();
1309*cb14a3feSDimitry Andric        if (__c == _CharT(',')) {
13100b57cec5SDimitry Andric          __is.get();
13110b57cec5SDimitry Andric          _Tp __i;
13120b57cec5SDimitry Andric          __is >> __i;
1313*cb14a3feSDimitry Andric          if (!__is.fail()) {
1314bdd1243dSDimitry Andric            std::ws(__is);
13150b57cec5SDimitry Andric            __c = __is.peek();
1316*cb14a3feSDimitry Andric            if (__c == _CharT(')')) {
13170b57cec5SDimitry Andric              __is.get();
13180b57cec5SDimitry Andric              __x = complex<_Tp>(__r, __i);
1319*cb14a3feSDimitry Andric            } else
13205ffd83dbSDimitry Andric              __is.setstate(__is.failbit);
1321*cb14a3feSDimitry Andric          } else
13225ffd83dbSDimitry Andric            __is.setstate(__is.failbit);
1323*cb14a3feSDimitry Andric        } else if (__c == _CharT(')')) {
13240b57cec5SDimitry Andric          __is.get();
13250b57cec5SDimitry Andric          __x = complex<_Tp>(__r, _Tp(0));
1326*cb14a3feSDimitry Andric        } else
13275ffd83dbSDimitry Andric          __is.setstate(__is.failbit);
1328*cb14a3feSDimitry Andric      } else
13295ffd83dbSDimitry Andric        __is.setstate(__is.failbit);
1330*cb14a3feSDimitry Andric    } else {
13310b57cec5SDimitry Andric      _Tp __r;
13320b57cec5SDimitry Andric      __is >> __r;
13330b57cec5SDimitry Andric      if (!__is.fail())
13340b57cec5SDimitry Andric        __x = complex<_Tp>(__r, _Tp(0));
13350b57cec5SDimitry Andric      else
13365ffd83dbSDimitry Andric        __is.setstate(__is.failbit);
13370b57cec5SDimitry Andric    }
1338*cb14a3feSDimitry Andric  } else
13395ffd83dbSDimitry Andric    __is.setstate(__is.failbit);
13400b57cec5SDimitry Andric  return __is;
13410b57cec5SDimitry Andric}
13420b57cec5SDimitry Andric
13430b57cec5SDimitry Andrictemplate <class _Tp, class _CharT, class _Traits>
1344bdd1243dSDimitry Andric_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>&
1345*cb14a3feSDimitry Andricoperator<<(basic_ostream<_CharT, _Traits>& __os, const complex<_Tp>& __x) {
13460b57cec5SDimitry Andric  basic_ostringstream<_CharT, _Traits> __s;
13470b57cec5SDimitry Andric  __s.flags(__os.flags());
13480b57cec5SDimitry Andric  __s.imbue(__os.getloc());
13490b57cec5SDimitry Andric  __s.precision(__os.precision());
13500b57cec5SDimitry Andric  __s << '(' << __x.real() << ',' << __x.imag() << ')';
13510b57cec5SDimitry Andric  return __os << __s.str();
13520b57cec5SDimitry Andric}
1353e8d8bef9SDimitry Andric#endif // !_LIBCPP_HAS_NO_LOCALIZATION
13540b57cec5SDimitry Andric
135506c3fb27SDimitry Andric#if _LIBCPP_STD_VER >= 14
13560b57cec5SDimitry Andric// Literal suffix for complex number literals [complex.literals]
1357*cb14a3feSDimitry Andricinline namespace literals {
1358*cb14a3feSDimitry Andricinline namespace complex_literals {
1359*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI inline constexpr complex<long double> operator""il(long double __im) { return {0.0l, __im}; }
13600b57cec5SDimitry Andric
1361*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI inline constexpr complex<long double> operator""il(unsigned long long __im) {
13620b57cec5SDimitry Andric  return {0.0l, static_cast<long double>(__im)};
13630b57cec5SDimitry Andric}
13640b57cec5SDimitry Andric
1365*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI inline constexpr complex<double> operator""i(long double __im) {
13660b57cec5SDimitry Andric  return {0.0, static_cast<double>(__im)};
13670b57cec5SDimitry Andric}
13680b57cec5SDimitry Andric
1369*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI inline constexpr complex<double> operator""i(unsigned long long __im) {
13700b57cec5SDimitry Andric  return {0.0, static_cast<double>(__im)};
13710b57cec5SDimitry Andric}
13720b57cec5SDimitry Andric
1373*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI inline constexpr complex<float> operator""if(long double __im) {
13740b57cec5SDimitry Andric  return {0.0f, static_cast<float>(__im)};
13750b57cec5SDimitry Andric}
13760b57cec5SDimitry Andric
1377*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI inline constexpr complex<float> operator""if(unsigned long long __im) {
13780b57cec5SDimitry Andric  return {0.0f, static_cast<float>(__im)};
13790b57cec5SDimitry Andric}
13800eae32dcSDimitry Andric} // namespace complex_literals
13810eae32dcSDimitry Andric} // namespace literals
13820b57cec5SDimitry Andric#endif
13830b57cec5SDimitry Andric
13840b57cec5SDimitry Andric_LIBCPP_END_NAMESPACE_STD
13850b57cec5SDimitry Andric
138606c3fb27SDimitry Andric#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
13875f757f3fSDimitry Andric#  include <iosfwd>
13885f757f3fSDimitry Andric#  include <stdexcept>
138906c3fb27SDimitry Andric#  include <type_traits>
139006c3fb27SDimitry Andric#endif
139106c3fb27SDimitry Andric
13920b57cec5SDimitry Andric#endif // _LIBCPP_COMPLEX
1393