TRIQS/TRIQS 4.0.0
Researching Interacting Quantum Systems
Loading...
Searching...
No Matches
real_or_complex.hpp
Go to the documentation of this file.
1// Copyright (c) 2015-2018 Commissariat à l'énergie atomique et aux énergies alternatives (CEA)
2// Copyright (c) 2015-2018 Centre national de la recherche scientifique (CNRS)
3// Copyright (c) 2018-2019 Simons Foundation
4// Copyright (c) 2015 Igor Krivenko
5//
6// This program is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10//
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15//
16// You may obtain a copy of the License at
17// https://www.gnu.org/licenses/gpl-3.0.txt
18//
19// Authors: Igor Krivenko, Olivier Parcollet, Nils Wentzell
20
25
26#pragma once
27
28#include "./exceptions.hpp"
29#include "./numeric_ops.hpp"
30
31#include <cmath>
32#include <complex>
33#include <limits>
34#include <ostream>
35#include <utility>
36
37namespace triqs::utility {
38
43
57 bool _is_real = true;
58 std::complex<double> _x;
59
60 public:
62 real_or_complex() : _x(0) {}
63
68 real_or_complex(double x) : _x(x) {}
69
74 real_or_complex(std::complex<double> x) : _is_real(false), _x(std::move(x)) {}
75
80 bool is_real() const { return _is_real; }
81
86 explicit operator std::complex<double>() const { return _x; }
87
93 explicit operator double() const {
94 if (!_is_real) TRIQS_RUNTIME_ERROR << "Logic error : the number is not real, it is complex";
95 return real(_x);
96 }
97
105 a._x = -a._x;
106 return a;
107 }
108
115 friend double real(real_or_complex const &x) { return real(x._x); }
116
123 friend double imag(real_or_complex const &x) { return imag(x._x); }
124
131 friend double abs(real_or_complex const &x) { return std::abs(x._x); }
132
140 x._x = std::conj(x._x);
141 return x;
142 }
143
152 friend bool is_zero(real_or_complex const &x, double tolerance = 100 * std::numeric_limits<double>::epsilon()) {
154 if (x.is_real()) return is_zero(double(x), tolerance);
155 return is_zero(x._x, tolerance);
156 }
157
165 friend std::ostream &operator<<(std::ostream &out, real_or_complex const &x) {
166 if (x._is_real)
167 out << double(x);
168 else {
169 out << '(' << x._x.real();
170 if (not std::signbit(x._x.imag())) out << '+';
171 out << x._x.imag() << "j)";
172 }
173 return out;
174 }
175
182 bool operator==(real_or_complex const &x) const { return abs(_x - x._x) == 0; }
183
190 bool operator!=(real_or_complex const &x) const { return !operator==(x); }
191
192 // Compound assignment operators (+=, -=, *=, /=).
193#define MAKE_OP(OP) \
194 inline real_or_complex &operator OP(double y) { \
195 _x OP y; \
196 return *this; \
197 } \
198 inline real_or_complex &operator OP(std::complex<double> const &y) { \
199 _x OP y; \
200 _is_real = false; \
201 return *this; \
202 } \
203 inline real_or_complex &operator OP(real_or_complex const &y) { \
204 _x OP y._x; \
205 _is_real &= y._is_real; \
206 return *this; \
207 }
208
209 MAKE_OP(+=);
210 MAKE_OP(-=);
211 MAKE_OP(*=);
212 MAKE_OP(/=);
213#undef MAKE_OP
214 };
215
216 // Arithmetic operators (+, -, *, /) for utility::real_or_complex values.
217#define MAKE_OP(OP, OPC) \
218 inline real_or_complex operator OP(real_or_complex a, real_or_complex const &b) { \
219 a OPC b; \
220 return a; \
221 } \
222 inline real_or_complex operator OP(real_or_complex a, std::complex<double> const &b) { \
223 a OPC b; \
224 return a; \
225 } \
226 inline real_or_complex operator OP(real_or_complex a, double b) { \
227 a OPC b; \
228 return a; \
229 } \
230 inline real_or_complex operator OP(std::complex<double> const &a, real_or_complex b) { return a OP std::complex<double>(b); } \
231 inline real_or_complex operator OP(double a, real_or_complex b) { \
232 if (b.is_real()) \
233 return a OP double(b); \
234 else \
235 return a OP std::complex<double>(b); \
236 }
237
238 MAKE_OP(+, +=);
239 MAKE_OP(-, -=);
240 MAKE_OP(*, *=);
241 MAKE_OP(/, /=);
242#undef MAKE_OP
243
245
246} // namespace triqs::utility
real_or_complex()
Default construct a real value initialized to zero.
bool operator!=(real_or_complex const &x) const
Not-equal-to operator compares the underlying complex values exactly.
friend real_or_complex conj(real_or_complex x)
Complex conjugate of a utility::real_or_complex value.
bool operator==(real_or_complex const &x) const
Equal-to operator compares the underlying complex values exactly.
real_or_complex(double x)
Construct a real value.
real_or_complex(std::complex< double > x)
Construct a complex value.
bool is_real() const
Whether the stored value is real.
friend double imag(real_or_complex const &x)
Imaginary part of a utility::real_or_complex value.
friend real_or_complex operator-(real_or_complex a)
Unary minus operator for a utility::real_or_complex value.
friend double real(real_or_complex const &x)
Real part of a utility::real_or_complex value.
friend std::ostream & operator<<(std::ostream &out, real_or_complex const &x)
Write a utility::real_or_complex value to an output stream.
real_or_complex()
Default construct a real value initialized to zero.
friend bool is_zero(real_or_complex const &x, double tolerance=100 *std::numeric_limits< double >::epsilon())
Zero check for a utility::real_or_complex value.
friend double abs(real_or_complex const &x)
Absolute value of a utility::real_or_complex value.
TRIQS exception hierarchy and related macros.
#define TRIQS_RUNTIME_ERROR
Throw a triqs::runtime_error with the current source location.
bool is_zero(I const &x)
Exact zero check for integral values.
Numeric helpers overloaded for various types.