1#ifndef TRIQS_NEVANLINNA_COMPLEX_HPP
2#define TRIQS_NEVANLINNA_COMPLEX_HPP
5#include <boost/multiprecision/mpfr.hpp>
7#include <boost/multiprecision/cpp_dec_float.hpp>
10namespace triqs_Nevanlinna {
11 static constexpr int mp_digits = 100;
13 using real_mpt = boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, boost::multiprecision::et_off>;
15 using real_mpt = boost::multiprecision::number<boost::multiprecision::cpp_dec_float<mp_digits>, boost::multiprecision::et_off>;
22 template <>
class complex<triqs_Nevanlinna::real_mpt> {
25 using value_type = triqs_Nevanlinna::real_mpt;
28 complex(value_type re) : _re(re) {}
29 complex(value_type re, value_type im) : _re(re), _im(im) {}
32 requires(is_arithmetic_v<S>)
33 complex(S re) : _re(re) {}
36 requires(is_arithmetic_v<S>)
37 complex(
const complex<S> &cplx) : _re(cplx.real()), _im(cplx.imag()) {}
39 template <convertible_to<value_type> S> complex &operator=(
const complex<S> &rhs) {
45 template <convertible_to<value_type> S> complex &operator-=(
const complex<S> &rhs) {
51 template <convertible_to<value_type> S> complex &operator+=(
const complex<S> &rhs) {
57 template <convertible_to<value_type> S> complex &operator*=(
const complex<S> &rhs) {
62 template <convertible_to<value_type> S> complex &operator/=(
const complex<S> &rhs) {
67 template <convertible_to<value_type> S> complex &operator-=(
const S &rhs) {
72 template <convertible_to<value_type> S> complex &operator+=(
const S &rhs) {
77 template <convertible_to<value_type> S> complex &operator*=(
const S &rhs) {
83 template <convertible_to<value_type> S> complex &operator/=(
const S &rhs) {
89 complex operator-()
const {
return complex(-_re, -_im); }
91 friend inline auto operator*(
const complex &x,
const complex &y) {
94 return complex((xr * yr - xi * yi), (xr * yi + xi * yr));
97 friend inline auto operator/(
const complex &x,
const complex &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);
106 friend inline auto operator+(
const complex &x,
const complex &y) {
109 return complex((xr + yr), (xi + yi));
112 friend inline auto operator-(
const complex &x,
const complex &y) {
115 return complex((xr - yr), (xi - yi));
118 friend inline bool operator==(
const complex &x,
const complex &y) =
default;
120 template <convertible_to<value_type> S>
121 requires(!is_same_v<S, value_type>)
122 friend inline bool operator==(
const complex &x,
const S &y) {
123 return x.real() == y && x.imag() == 0;
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;
132 value_type real()
const {
return _re; }
133 value_type imag()
const {
return _im; }
135 friend inline auto real(
const complex &x) {
return x._re; }
136 friend inline auto imag(
const complex &x) {
return x._im; }
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()); }
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);
151 return complex<triqs_Nevanlinna::real_mpt>(x, y);
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());
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));