Namespaces
Variants
Views
Actions

Difference between revisions of "cpp/numeric/complex"

From cppreference.com
< cpp‎ | numeric
(Non-static data members: Split into array-oriented access and implementation notes, and expand possible implementations (see talk))
m (Example: demo effect of P2819.)
 
(26 intermediate revisions by 11 users not shown)
Line 2: Line 2:
 
{{cpp/numeric/complex/navbar}}
 
{{cpp/numeric/complex/navbar}}
 
{{dcl begin}}
 
{{dcl begin}}
{{dcl header | complex}}
+
{{dcl header|complex}}
{{dcl | num=1 | 1=
+
{{dcl|num=1|1=
 
template< class T >
 
template< class T >
 
class complex;
 
class complex;
 
}}
 
}}
{{dcl | num=2| 1=
+
{{dcl|num=2|until=c++23|
 
template<> class complex<float>;
 
template<> class complex<float>;
 
}}
 
}}
{{dcl | num=3| 1=
+
{{dcl|num=3|until=c++23|
 
template<> class complex<double>;
 
template<> class complex<double>;
 
}}
 
}}
{{dcl | num=4| 1=
+
{{dcl|num=4|until=c++23|
 
template<> class complex<long double>;
 
template<> class complex<long double>;
 
}}
 
}}
 
{{dcl end}}
 
{{dcl end}}
  
The specializations {{c|std::complex<float>}}, {{c|std::complex<double>}}, and {{c|std::complex<long double>}} are {{concept|LiteralType}}s for representing and manipulating [[enwiki:Complex_number|complex numbers]].  
+
Specializations of {{tt|std::complex}} for cv-unqualified {{rev inl|until=c++23|standard}} {{lsd|cpp/language/types#Floating-point types}} are {{rev inl|since=c++23|{{named req|TriviallyCopyable}}}} {{named req|LiteralType}}s for representing and manipulating {{enwiki|complex number}}.
  
The effect of instantiating the template {{tt|complex}} for any other type is unspecified.
+
===Template parameters===
 +
{{par begin}}
 +
{{par|T|the type of the real and imaginary parts. The behavior is unspecified (and may fail to compile) if {{tt|T}} is not a cv-unqualified {{rev inl|until=c++23|standard}} floating-point type and undefined if {{tt|T}} is not {{named req|NumericType}}.}}
 +
{{par end}}
  
 
===Member types===
 
===Member types===
 
{{dsc begin}}
 
{{dsc begin}}
{{dsc hitem | Member type | Definition}}
+
{{dsc hitem|Member type|Definition}}
{{dsc | {{tt|value_type}} | {{tt|T}}}}
+
{{dsc|{{tt|value_type}}|{{tt|T}}}}
 
{{dsc end}}
 
{{dsc end}}
  
 
===Member functions===
 
===Member functions===
 
{{dsc begin}}
 
{{dsc begin}}
{{dsc inc | cpp/numeric/complex/dsc complex}}
+
{{dsc inc|cpp/numeric/complex/dsc complex}}
{{dsc inc | cpp/numeric/complex/dsc operator{{=}}}}
+
{{dsc inc|cpp/numeric/complex/dsc operator{{=}}}}
{{dsc inc | cpp/numeric/complex/dsc real}}
+
{{dsc inc|cpp/numeric/complex/dsc real}}
{{dsc inc | cpp/numeric/complex/dsc imag}}
+
{{dsc inc|cpp/numeric/complex/dsc imag}}
{{dsc inc | cpp/numeric/complex/dsc operator_arith}}
+
{{dsc inc|cpp/numeric/complex/dsc operator_arith}}
 
{{dsc end}}
 
{{dsc end}}
  
 
===Non-member functions===
 
===Non-member functions===
 
{{dsc begin}}
 
{{dsc begin}}
{{dsc inc | cpp/numeric/complex/dsc operator_arith2}}
+
{{dsc inc|cpp/numeric/complex/dsc operator_arith2}}
{{dsc inc | cpp/numeric/complex/dsc operator_arith3}}
+
{{dsc inc|cpp/numeric/complex/dsc operator_arith3}}
{{dsc inc | cpp/numeric/complex/dsc operator_cmp}}
+
{{dsc inc|cpp/numeric/complex/dsc operator_cmp}}
{{dsc inc | cpp/numeric/complex/dsc operator_ltltgtgt}}
+
{{dsc inc|cpp/numeric/complex/dsc operator_ltltgtgt}}
{{dsc inc | cpp/numeric/complex/dsc real2}}
+
{{dsc inc|cpp/numeric/complex/dsc get}}
{{dsc inc | cpp/numeric/complex/dsc imag2}}
+
{{dsc inc|cpp/numeric/complex/dsc real2}}
{{dsc inc | cpp/numeric/complex/dsc abs}}
+
{{dsc inc|cpp/numeric/complex/dsc imag2}}
{{dsc inc | cpp/numeric/complex/dsc arg}}
+
{{dsc inc|cpp/numeric/complex/dsc abs}}
{{dsc inc | cpp/numeric/complex/dsc norm}}
+
{{dsc inc|cpp/numeric/complex/dsc arg}}
{{dsc inc | cpp/numeric/complex/dsc conj}}
+
{{dsc inc|cpp/numeric/complex/dsc norm}}
{{dsc inc | cpp/numeric/complex/dsc proj}}
+
{{dsc inc|cpp/numeric/complex/dsc conj}}
{{dsc inc | cpp/numeric/complex/dsc polar}}
+
{{dsc inc|cpp/numeric/complex/dsc proj}}
 +
{{dsc inc|cpp/numeric/complex/dsc polar}}
  
{{dsc h2 | Exponential functions}}
+
{{dsc h2|Exponential functions}}
{{dsc inc | cpp/numeric/complex/dsc exp}}
+
{{dsc inc|cpp/numeric/complex/dsc exp}}
{{dsc inc | cpp/numeric/complex/dsc log}}
+
{{dsc inc|cpp/numeric/complex/dsc log}}
{{dsc inc | cpp/numeric/complex/dsc log10}}
+
{{dsc inc|cpp/numeric/complex/dsc log10}}
  
{{dsc h2 | Power functions}}
+
{{dsc h2|Power functions}}
{{dsc inc | cpp/numeric/complex/dsc pow}}
+
{{dsc inc|cpp/numeric/complex/dsc pow}}
{{dsc inc | cpp/numeric/complex/dsc sqrt}}
+
{{dsc inc|cpp/numeric/complex/dsc sqrt}}
  
{{dsc h2 | Trigonometric functions}}
+
{{dsc h2|Trigonometric functions}}
{{dsc inc | cpp/numeric/complex/dsc sin}}
+
{{dsc inc|cpp/numeric/complex/dsc sin}}
{{dsc inc | cpp/numeric/complex/dsc cos}}
+
{{dsc inc|cpp/numeric/complex/dsc cos}}
{{dsc inc | cpp/numeric/complex/dsc tan}}
+
{{dsc inc|cpp/numeric/complex/dsc tan}}
{{dsc inc | cpp/numeric/complex/dsc asin}}
+
{{dsc inc|cpp/numeric/complex/dsc asin}}
{{dsc inc | cpp/numeric/complex/dsc acos}}
+
{{dsc inc|cpp/numeric/complex/dsc acos}}
{{dsc inc | cpp/numeric/complex/dsc atan}}
+
{{dsc inc|cpp/numeric/complex/dsc atan}}
  
{{dsc h2 | Hyperbolic functions}}
+
{{dsc h2|Hyperbolic functions}}
{{dsc inc | cpp/numeric/complex/dsc sinh}}
+
{{dsc inc|cpp/numeric/complex/dsc sinh}}
{{dsc inc | cpp/numeric/complex/dsc cosh}}
+
{{dsc inc|cpp/numeric/complex/dsc cosh}}
{{dsc inc | cpp/numeric/complex/dsc tanh}}
+
{{dsc inc|cpp/numeric/complex/dsc tanh}}
{{dsc inc | cpp/numeric/complex/dsc asinh}}
+
{{dsc inc|cpp/numeric/complex/dsc asinh}}
{{dsc inc | cpp/numeric/complex/dsc acosh}}
+
{{dsc inc|cpp/numeric/complex/dsc acosh}}
{{dsc inc | cpp/numeric/complex/dsc atanh}}
+
{{dsc inc|cpp/numeric/complex/dsc atanh}}
 +
{{dsc end}}
 +
 
 +
===Helper types===
 +
{{dsc begin}}
 +
{{dsc inc|cpp/numeric/complex/dsc tuple_size}}
 +
{{dsc inc|cpp/numeric/complex/dsc tuple_element}}
 
{{dsc end}}
 
{{dsc end}}
  
 
===Array-oriented access===
 
===Array-oriented access===
{{rev begin}}
+
For any object {{c|z}} of type {{tt|std::complex<T>}}, {{c|reinterpret_cast<T(&)[2]>(z)[0]}} is the real part of {{c|z}} and {{c|reinterpret_cast<T(&)[2]>(z)[1]}} is the imaginary part of {{c|z}}.
{{rev|since=c++11|
+
For any object {{tt|z}} of type {{tt|complex<T>}}, {{c|reinterpret_cast<T(&)[2]>(z)[0]}} is the real part of z and {{c|reinterpret_cast<T(&)[2]>(z)[1]}} is the imaginary part of z.
+
  
For any pointer to an element of an array of {{tt|complex<T>}} named {{tt|p}} and any valid array index {{c|i}}, {{c|reinterpret_cast<T*>(p)[2*i]}} is the real part of the complex number {{c|p[i]}}, and {{c|reinterpret_cast<T*>(p)[2*i + 1]}} is the imaginary part of the complex number {{c|p[i]}}
+
For any pointer to an element of an array of {{tt|std::complex<T>}} named {{c|p}} and any valid array index {{c|i}}, {{c|reinterpret_cast<T*>(p)[2 * i]}} is the real part of the complex number {{c|p[i]}}, and {{c|reinterpret_cast<T*>(p)[2 * i + 1]}} is the imaginary part of the complex number {{c|p[i]}}.
  
The intent of this requirement is to preserve binary compatibility between the C++ library complex number types and the [[c/language/arithmetic_types#Complex_floating_types|C language complex number types]] (and arrays thereof), which have an identical object representation requirement.
+
The intent of this requirement is to preserve binary compatibility between the C++ library complex number types and the [[c/language/arithmetic types#Complex floating types|C language complex number types]] (and arrays thereof), which have an identical object representation requirement.
}}
+
{{rev end}}
+
  
=== Implementation notes ===
+
===Implementation notes===
{{rev begin}}
+
In order to satisfy the requirements of array-oriented access, an implementation is constrained to store the real and imaginary parts of a {{tt|std::complex}} specialization in separate and adjacent memory locations. Possible declarations for its non-static data members include:
{{rev|since=c++11|
+
In order to satisfy the requirements of array-oriented access, an implementation is constrained to store the real and imaginary components of a {{lc|std::complex}} specialization in separate and adjacent memory locations. Possible declarations for its non-static data members include:
+
  
* an array of type {{c|value_type[2]}}, with the first element holding the real component and the second element holding the imaginary component;
+
* an array of type {{tt|value_type[2]}}, with the first element holding the real part and the second element holding the imaginary part (e.g. Microsoft Visual Studio);
* a single member of type {{c|value_type _Complex}} (encapsulating the corresponding [[c/language/arithmetic_types#Complex_floating_types|C language complex number type]]);
+
* a single member of type {{tt|value_type _Complex}} (encapsulating the corresponding [[c/language/arithmetic types#Complex floating types|C language complex number type]]) (e.g. GNU libstdc++);
* two members of type {{c|value_type}}, with the same member access, holding the real and the imaginary components respectively, and having implementation-specific attributes as required to permit the above {{c|reinterpret_cast}}.
+
* two members of type {{tt|value_type}}, with the same member access, holding the real and the imaginary parts respectively (e.g. LLVM libc++).
  
An implementation cannot declare additional non-static data members that would occupy storage disjoint from the real and imaginary components, and must ensure that the class template specialization does not contain any padding.
+
An implementation cannot declare additional non-static data members that would occupy storage disjoint from the real and imaginary parts, and must ensure that the class template specialization does not contain any [[cpp/language/object#Object representation and value representation|padding bit]]. The implementation must also ensure that optimizations to array access account for the possibility that a pointer to {{tt|value_type}} may be aliasing a {{tt|std::complex}} specialization or array thereof.
}}
+
{{rev end}}
+
  
 
===Literals===
 
===Literals===
 
{{dsc begin}}
 
{{dsc begin}}
{{dsc namespace | std::literals::complex_literals | inline=true }}
+
{{dsc namespace|std::literals::complex_literals|inline=true}}
{{dsc inc | cpp/numeric/dsc operator""i}}
+
{{dsc inc|cpp/numeric/dsc operator""i}}
 
{{dsc end}}
 
{{dsc end}}
 +
 +
===Notes===
 +
{{ftm begin|sort=yes}}
 +
{{ftm|__cpp_lib_constexpr_complex|rowspan="2"|std=C++20|value=201711L|{{c/core|constexpr}} simple complex mathematical functions in {{header|complex}}}}
 +
{{ftm|-|More {{c/core|constexpr}} for {{header|complex}}|std=C++26|value=202306L}}
 +
{{ftm|__cpp_lib_tuple_like|std=C++26|value=202311L|Add tuple protocol to {{tt|std::complex}}}}
 +
{{ftm end}}
  
 
===Example===
 
===Example===
 
{{example
 
{{example
 
|code=
 
|code=
#include <iostream>
 
#include <iomanip>
 
#include <complex>
 
 
#include <cmath>
 
#include <cmath>
 +
#include <complex>
 +
#include <iomanip>
 +
#include <iostream>
 +
#include <ranges>
  
 
int main()
 
int main()
Line 120: Line 130:
 
     using namespace std::complex_literals;
 
     using namespace std::complex_literals;
 
     std::cout << std::fixed << std::setprecision(1);
 
     std::cout << std::fixed << std::setprecision(1);
   
+
 
     std::complex<double> z1 = 1i * 1i;     // imaginary unit squared
+
     std::complex<double> z1 = 1i * 1i; // imaginary unit squared
 
     std::cout << "i * i = " << z1 << '\n';
 
     std::cout << "i * i = " << z1 << '\n';
  
Line 127: Line 137:
 
     std::cout << "pow(i, 2) = " << z2 << '\n';
 
     std::cout << "pow(i, 2) = " << z2 << '\n';
  
     double PI = std::acos(-1);
+
     const double PI = std::acos(-1); // or std::numbers::pi in C++20
 
     std::complex<double> z3 = std::exp(1i * PI); // Euler's formula
 
     std::complex<double> z3 = std::exp(1i * PI); // Euler's formula
 
     std::cout << "exp(i * pi) = " << z3 << '\n';
 
     std::cout << "exp(i * pi) = " << z3 << '\n';
  
     std::complex<double> z4 = 1. + 2i, z5 = 1. - 2i; // conjugates
+
     std::complex<double> z4 = 1.0 + 2i, z5 = 1.0 - 2i; // conjugates
     std::cout << "(1+2i)*(1-2i) = " << z4*z5 << '\n';
+
     std::cout << "(1 + 2i) * (1 - 2i) = " << z4 * z5 << '\n';
 +
 
 +
    const auto zz = {0.0 + 1i, 2.0 + 3i, 4.0 + 5i};
 +
#if __cpp_lib_tuple_like >= 202311L
 +
    for (double re : zz {{!}} std::views::keys)
 +
        std::cout << re << ' ';
 +
    std::cout << '\n';
 +
    for (double im : zz {{!}} std::views::values)
 +
        std::cout << im << ' ';
 +
    std::cout << '\n';
 +
#else
 +
    for (double re : zz {{!}} std::views::transform([](auto z){ return z.real(); }))
 +
        std::cout << re << ' ';
 +
    std::cout << '\n';
 +
    for (double im : zz {{!}} std::views::transform([](auto z){ return z.imag(); }))
 +
        std::cout << im << ' ';
 +
    std::cout << '\n';
 +
#endif
 
}
 
}
 
|output=
 
|output=
Line 138: Line 165:
 
pow(i, 2) = (-1.0,0.0)
 
pow(i, 2) = (-1.0,0.0)
 
exp(i * pi) = (-1.0,0.0)
 
exp(i * pi) = (-1.0,0.0)
(1+2i)*(1-2i) = (5.0,0.0)
+
(1 + 2i) * (1 - 2i) = (5.0,0.0)
 +
0.0 2.0 4.0
 +
1.0 3.0 5.0
 
}}
 
}}
 +
 +
===Defect reports===
 +
{{dr list begin}}
 +
{{dr list item|wg=lwg|dr=387|std=C++98|before={{tt|std::complex}} was not guaranteed to be compatible with C {{tt|complex}}|after=guaranteed to be compatible}}
 +
{{dr list end}}
 +
 
===See also===
 
===See also===
 
{{dsc begin}}
 
{{dsc begin}}
{{dsc see c | c/numeric/complex | Complex number arithmetic}}
+
{{dsc see c|c/numeric/complex|Complex number arithmetic|nomono=true}}
 
{{dsc end}}
 
{{dsc end}}
  
[[de:cpp/numeric/complex]]
+
{{langlinks|de|es|fr|it|ja|pt|ru|zh}}
[[es:cpp/numeric/complex]]
+
[[fr:cpp/numeric/complex]]
+
[[it:cpp/numeric/complex]]
+
[[ja:cpp/numeric/complex]]
+
[[pt:cpp/numeric/complex]]
+
[[ru:cpp/numeric/complex]]
+
[[zh:cpp/numeric/complex]]
+

Latest revision as of 07:50, 5 August 2024

 
 
 
 
Defined in header <complex>
template< class T >
class complex;
(1)
template<> class complex<float>;
(2) (until C++23)
template<> class complex<double>;
(3) (until C++23)
template<> class complex<long double>;
(4) (until C++23)

Specializations of std::complex for cv-unqualified standard(until C++23) floating-point types are TriviallyCopyable(since C++23) LiteralTypes for representing and manipulating complex number.

Contents

[edit] Template parameters

T - the type of the real and imaginary parts. The behavior is unspecified (and may fail to compile) if T is not a cv-unqualified standard(until C++23) floating-point type and undefined if T is not NumericType.

[edit] Member types

Member type Definition
value_type T

[edit] Member functions

constructs a complex number
(public member function) [edit]
assigns the contents
(public member function) [edit]
accesses the real part of the complex number
(public member function) [edit]
accesses the imaginary part of the complex number
(public member function) [edit]
compound assignment of two complex numbers or a complex and a scalar
(public member function) [edit]

[edit] Non-member functions

applies unary operators to complex numbers
(function template) [edit]
performs complex number arithmetic on two complex values or a complex and a scalar
(function template) [edit]
(removed in C++20)
compares two complex numbers or a complex and a scalar
(function template) [edit]
serializes and deserializes a complex number
(function template) [edit]
obtains a reference to real or imaginary part from a std::complex
(function template) [edit]
returns the real part
(function template) [edit]
returns the imaginary part
(function template) [edit]
returns the magnitude of a complex number
(function template) [edit]
returns the phase angle
(function template) [edit]
returns the squared magnitude
(function template) [edit]
returns the complex conjugate
(function template) [edit]
(C++11)
returns the projection onto the Riemann sphere
(function template) [edit]
constructs a complex number from magnitude and phase angle
(function template) [edit]
Exponential functions
complex base e exponential
(function template) [edit]
complex natural logarithm with the branch cuts along the negative real axis
(function template) [edit]
complex common logarithm with the branch cuts along the negative real axis
(function template) [edit]
Power functions
complex power, one or both arguments may be a complex number
(function template) [edit]
complex square root in the range of the right half-plane
(function template) [edit]
Trigonometric functions
computes sine of a complex number (sin(z))
(function template) [edit]
computes cosine of a complex number (cos(z))
(function template) [edit]
computes tangent of a complex number (tan(z))
(function template) [edit]
computes arc sine of a complex number (arcsin(z))
(function template) [edit]
computes arc cosine of a complex number (arccos(z))
(function template) [edit]
computes arc tangent of a complex number (arctan(z))
(function template) [edit]
Hyperbolic functions
computes hyperbolic sine of a complex number (sinh(z))
(function template) [edit]
computes hyperbolic cosine of a complex number (cosh(z))
(function template) [edit]
computes hyperbolic tangent of a complex number (tanh(z))
(function template) [edit]
computes area hyperbolic sine of a complex number (arsinh(z))
(function template) [edit]
computes area hyperbolic cosine of a complex number (arcosh(z))
(function template) [edit]
computes area hyperbolic tangent of a complex number (artanh(z))
(function template) [edit]

[edit] Helper types

obtains the size of a std::complex
(class template specialization) [edit]
obtains the underlying real and imaginary number type of a std::complex
(class template specialization) [edit]

[edit] Array-oriented access

For any object z of type std::complex<T>, reinterpret_cast<T(&)[2]>(z)[0] is the real part of z and reinterpret_cast<T(&)[2]>(z)[1] is the imaginary part of z.

For any pointer to an element of an array of std::complex<T> named p and any valid array index i, reinterpret_cast<T*>(p)[2 * i] is the real part of the complex number p[i], and reinterpret_cast<T*>(p)[2 * i + 1] is the imaginary part of the complex number p[i].

The intent of this requirement is to preserve binary compatibility between the C++ library complex number types and the C language complex number types (and arrays thereof), which have an identical object representation requirement.

[edit] Implementation notes

In order to satisfy the requirements of array-oriented access, an implementation is constrained to store the real and imaginary parts of a std::complex specialization in separate and adjacent memory locations. Possible declarations for its non-static data members include:

  • an array of type value_type[2], with the first element holding the real part and the second element holding the imaginary part (e.g. Microsoft Visual Studio);
  • a single member of type value_type _Complex (encapsulating the corresponding C language complex number type) (e.g. GNU libstdc++);
  • two members of type value_type, with the same member access, holding the real and the imaginary parts respectively (e.g. LLVM libc++).

An implementation cannot declare additional non-static data members that would occupy storage disjoint from the real and imaginary parts, and must ensure that the class template specialization does not contain any padding bit. The implementation must also ensure that optimizations to array access account for the possibility that a pointer to value_type may be aliasing a std::complex specialization or array thereof.

[edit] Literals

Defined in inline namespace std::literals::complex_literals
a std::complex literal representing purely imaginary number
(function) [edit]

[edit] Notes

Feature-test macro Value Std Feature
__cpp_lib_constexpr_complex 201711L (C++20) constexpr simple complex mathematical functions in <complex>
202306L (C++26) More constexpr for <complex>
__cpp_lib_tuple_like 202311L (C++26) Add tuple protocol to std::complex

[edit] Example

#include <cmath>
#include <complex>
#include <iomanip>
#include <iostream>
#include <ranges>
 
int main()
{
    using namespace std::complex_literals;
    std::cout << std::fixed << std::setprecision(1);
 
    std::complex<double> z1 = 1i * 1i; // imaginary unit squared
    std::cout << "i * i = " << z1 << '\n';
 
    std::complex<double> z2 = std::pow(1i, 2); // imaginary unit squared
    std::cout << "pow(i, 2) = " << z2 << '\n';
 
    const double PI = std::acos(-1); // or std::numbers::pi in C++20
    std::complex<double> z3 = std::exp(1i * PI); // Euler's formula
    std::cout << "exp(i * pi) = " << z3 << '\n';
 
    std::complex<double> z4 = 1.0 + 2i, z5 = 1.0 - 2i; // conjugates
    std::cout << "(1 + 2i) * (1 - 2i) = " << z4 * z5 << '\n';
 
    const auto zz = {0.0 + 1i, 2.0 + 3i, 4.0 + 5i};
#if __cpp_lib_tuple_like >= 202311L
    for (double re : zz | std::views::keys)
        std::cout << re << ' ';
    std::cout << '\n';
    for (double im : zz | std::views::values)
        std::cout << im << ' ';
    std::cout << '\n';
#else
    for (double re : zz | std::views::transform([](auto z){ return z.real(); }))
        std::cout << re << ' ';
    std::cout << '\n';
    for (double im : zz | std::views::transform([](auto z){ return z.imag(); }))
        std::cout << im << ' ';
    std::cout << '\n';
#endif
}

Output:

i * i = (-1.0,0.0)
pow(i, 2) = (-1.0,0.0)
exp(i * pi) = (-1.0,0.0)
(1 + 2i) * (1 - 2i) = (5.0,0.0)
0.0 2.0 4.0
1.0 3.0 5.0

[edit] Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

DR Applied to Behavior as published Correct behavior
LWG 387 C++98 std::complex was not guaranteed to be compatible with C complex guaranteed to be compatible

[edit] See also

C documentation for Complex number arithmetic