TRIQS/triqs_Nevanlinna 4.0.0
A TRIQS application
Loading...
Searching...
No Matches
complex.hpp
1#ifndef TRIQS_NEVANLINNA_COMPLEX_HPP
2#define TRIQS_NEVANLINNA_COMPLEX_HPP
3
4#ifdef WITH_MPFR
5#include <boost/multiprecision/mpfr.hpp>
6#else
7#include <boost/multiprecision/cpp_dec_float.hpp>
8#endif
9
10namespace triqs_Nevanlinna {
11 static constexpr int mp_digits = 100;
12#ifdef WITH_MPFR
13 using real_mpt = boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, boost::multiprecision::et_off>;
14#else
15 using real_mpt = boost::multiprecision::number<boost::multiprecision::cpp_dec_float<mp_digits>, boost::multiprecision::et_off>;
16#endif
17} // namespace triqs_Nevanlinna
18
19namespace std {
20
21 // std::complex explicit template specialization for triqs_Nevanlinna::real_mpt to overcome libc++ limitations.
22 template <> class complex<triqs_Nevanlinna::real_mpt> {
23
24 public:
25 using value_type = triqs_Nevanlinna::real_mpt;
26
27 complex() = default;
28 complex(value_type re) : _re(re) {}
29 complex(value_type re, value_type im) : _re(re), _im(im) {}
30
31 template <typename S>
32 requires(is_arithmetic_v<S>)
33 complex(S re) : _re(re) {}
34
35 template <typename S>
36 requires(is_arithmetic_v<S>)
37 complex(const complex<S> &cplx) : _re(cplx.real()), _im(cplx.imag()) {}
38
39 template <convertible_to<value_type> S> complex &operator=(const complex<S> &rhs) {
40 _re = rhs.real();
41 _im = rhs.imag();
42 return *this;
43 }
44
45 template <convertible_to<value_type> S> complex &operator-=(const complex<S> &rhs) {
46 _re -= rhs.real();
47 _im -= rhs.imag();
48 return *this;
49 }
50
51 template <convertible_to<value_type> S> complex &operator+=(const complex<S> &rhs) {
52 _re += rhs.real();
53 _im += rhs.imag();
54 return *this;
55 }
56
57 template <convertible_to<value_type> S> complex &operator*=(const complex<S> &rhs) {
58 *this = *this * rhs;
59 return *this;
60 }
61
62 template <convertible_to<value_type> S> complex &operator/=(const complex<S> &rhs) {
63 *this = *this / rhs;
64 return *this;
65 }
66
67 template <convertible_to<value_type> S> complex &operator-=(const S &rhs) {
68 _re -= rhs;
69 return *this;
70 }
71
72 template <convertible_to<value_type> S> complex &operator+=(const S &rhs) {
73 _re += rhs;
74 return *this;
75 }
76
77 template <convertible_to<value_type> S> complex &operator*=(const S &rhs) {
78 _re *= rhs;
79 _im *= rhs;
80 return *this;
81 }
82
83 template <convertible_to<value_type> S> complex &operator/=(const S &rhs) {
84 _re /= rhs;
85 _im /= rhs;
86 return *this;
87 }
88
89 complex operator-() const { return complex(-_re, -_im); }
90
91 friend inline auto operator*(const complex &x, const complex &y) {
92 auto [xr, xi] = x;
93 auto [yr, yi] = y;
94 return complex((xr * yr - xi * yi), (xr * yi + xi * yr));
95 }
96
97 friend inline auto operator/(const complex &x, const complex &y) {
98 auto [xr, xi] = x;
99 auto [yr, yi] = y;
100 auto denom = yr * yr + yi * yi;
101 auto r = (xr * yr + xi * yi) / denom;
102 auto i = (xi * yr - xr * yi) / denom;
103 return complex(r, i);
104 }
105
106 friend inline auto operator+(const complex &x, const complex &y) {
107 auto [xr, xi] = x;
108 auto [yr, yi] = y;
109 return complex((xr + yr), (xi + yi));
110 }
111
112 friend inline auto operator-(const complex &x, const complex &y) {
113 auto [xr, xi] = x;
114 auto [yr, yi] = y;
115 return complex((xr - yr), (xi - yi));
116 }
117
118 friend inline bool operator==(const complex &x, const complex &y) = default;
119
120 template <convertible_to<value_type> S>
121 requires(!is_same_v<S, value_type>) // value_type itself is handled by the standard complex<T> == T overload
122 friend inline bool operator==(const complex &x, const S &y) {
123 return x.real() == y && x.imag() == 0;
124 }
125
126 template <convertible_to<value_type> S>
127 requires(!is_same_v<S, value_type>)
128 friend inline bool operator==(const S &y, const complex &x) {
129 return x.real() == y && x.imag() == 0;
130 }
131
132 value_type real() const { return _re; }
133 value_type imag() const { return _im; }
134
135 friend inline auto real(const complex &x) { return x._re; }
136 friend inline auto imag(const complex &x) { return x._im; }
137
138 private:
139 value_type _re = 0;
140 value_type _im = 0;
141 };
142
143 inline auto abs(const complex<triqs_Nevanlinna::real_mpt> &x) { return sqrt(x.real() * x.real() + x.imag() * x.imag()); }
144 inline auto conj(const complex<triqs_Nevanlinna::real_mpt> &x) { return complex<triqs_Nevanlinna::real_mpt>(x.real(), -x.imag()); }
145
146 inline auto polar(const triqs_Nevanlinna::real_mpt &rho, const triqs_Nevanlinna::real_mpt &arg) {
147 triqs_Nevanlinna::real_mpt x = boost::multiprecision::cos(arg);
148 triqs_Nevanlinna::real_mpt y = boost::multiprecision::sin(arg);
149 x *= rho;
150 y *= rho;
151 return complex<triqs_Nevanlinna::real_mpt>(x, y);
152 }
153
154 inline auto arg(const complex<triqs_Nevanlinna::real_mpt> &x) {
155 triqs_Nevanlinna::real_mpt arg_;
156 arg_ = boost::multiprecision::atan2(x.imag(), x.real());
157 return arg_;
158 }
159
160 inline auto sqrt(const complex<triqs_Nevanlinna::real_mpt> &x) {
161 return polar(boost::multiprecision::sqrt(abs(x)), arg(x) / triqs_Nevanlinna::real_mpt(2));
162 }
163
164} // namespace std
165
166#endif //TRIQS_NEVANLINNA_COMPLEX_HPP