xref: /petsc/include/petsccxxcomplexfix.h (revision a966371c440b1408f7dc3455f51c619806857f77)
139829747SLisandro Dalcin #if !defined(PETSCCXXCOMPLEXFIX_H)
239829747SLisandro Dalcin #define PETSCCXXCOMPLEXFIX_H
339829747SLisandro Dalcin 
4f636a84aSBarry Smith /*
54cdc28b3SLisandro Dalcin     The pragma below silence all compiler warnings comming from code in this header file.
64cdc28b3SLisandro Dalcin     In particular, it silences `-Wfloat-equal` warnings in `operator==()` and `operator!=` below.
74cdc28b3SLisandro Dalcin     Other compilers beyond GCC support this pragma.
84cdc28b3SLisandro Dalcin */
94cdc28b3SLisandro Dalcin #if defined(__GNUC__) && (__GNUC__ >= 4)
104cdc28b3SLisandro Dalcin #pragma GCC system_header
114cdc28b3SLisandro Dalcin #endif
124cdc28b3SLisandro Dalcin 
134cdc28b3SLisandro Dalcin /*
14f636a84aSBarry Smith      Defines additional operator overloading for the C++ complex class that are "missing" in the standard
15f636a84aSBarry Smith      include files. For example, the code fragment
16f636a84aSBarry Smith 
17f636a84aSBarry Smith      std::complex<double> c = 22.0;
18f636a84aSBarry Smith      c = 11 + c;
19f636a84aSBarry Smith 
20f636a84aSBarry Smith      will produce a compile time error such as
21f636a84aSBarry Smith 
22f636a84aSBarry Smith      error: no match for 'operator+' (operand types are 'int' and 'std::complex<double>')
23f636a84aSBarry Smith 
24f636a84aSBarry Smith      The code fragment
25f636a84aSBarry Smith 
26f636a84aSBarry Smith      std::complex<float> c = 22.0;
27f636a84aSBarry Smith      c = 11.0 + c;
28f636a84aSBarry Smith 
29f636a84aSBarry Smith      will produce a compile time error such as
30f636a84aSBarry Smith 
31f636a84aSBarry Smith      error: no match for 'operator+' (operand types are 'double' and 'std::complex<float>')
32f636a84aSBarry Smith 
33f636a84aSBarry Smith      This deficiency means one may need to write cumbersome code while working with the C++ complex classes.
34f636a84aSBarry Smith 
35f636a84aSBarry Smith      This include file defines a few additional operator overload methods for the C++ complex classes to handle
36f636a84aSBarry Smith      these cases naturally within PETSc code.
37f636a84aSBarry Smith 
38*a966371cSJunchao Zhang      This file is included in petscsystypes.h when feasible. In the small number of cases where these additional methods
39*a966371cSJunchao Zhang      may conflict with other code one may add '#define PETSC_SKIP_CXX_COMPLEX_FIX 1' before including any PETSc include
40*a966371cSJunchao Zhang      files to prevent these methods from being provided.
41f636a84aSBarry Smith */
42f636a84aSBarry Smith 
4302c9f0b5SLisandro Dalcin #if defined(__GNUC__) && (__GNUC__ >= 4)
4402c9f0b5SLisandro Dalcin #pragma GCC system_header
4502c9f0b5SLisandro Dalcin #endif
4602c9f0b5SLisandro Dalcin 
4739829747SLisandro Dalcin #define PETSC_CXX_COMPLEX_FIX(Type) \
48d4baf660SLisandro Dalcin static inline PetscComplex operator+(const PetscComplex& lhs, const Type& rhs) { return const_cast<PetscComplex&>(lhs) + PetscReal(rhs); } \
49d4baf660SLisandro Dalcin static inline PetscComplex operator+(const Type& lhs, const PetscComplex& rhs) { return PetscReal(lhs) + const_cast<PetscComplex&>(rhs); } \
50d4baf660SLisandro Dalcin static inline PetscComplex operator-(const PetscComplex& lhs, const Type& rhs) { return const_cast<PetscComplex&>(lhs) - PetscReal(rhs); } \
51d4baf660SLisandro Dalcin static inline PetscComplex operator-(const Type& lhs, const PetscComplex& rhs) { return PetscReal(lhs) - const_cast<PetscComplex&>(rhs); } \
52d4baf660SLisandro Dalcin static inline PetscComplex operator*(const PetscComplex& lhs, const Type& rhs) { return const_cast<PetscComplex&>(lhs) * PetscReal(rhs); } \
53d4baf660SLisandro Dalcin static inline PetscComplex operator*(const Type& lhs, const PetscComplex& rhs) { return PetscReal(lhs) * const_cast<PetscComplex&>(rhs); } \
54d4baf660SLisandro Dalcin static inline PetscComplex operator/(const PetscComplex& lhs, const Type& rhs) { return const_cast<PetscComplex&>(lhs) / PetscReal(rhs); } \
55d4baf660SLisandro Dalcin static inline PetscComplex operator/(const Type& lhs, const PetscComplex& rhs) { return PetscReal(lhs) / const_cast<PetscComplex&>(rhs); } \
56b6f7a5a8SLisandro Dalcin static inline bool operator==(const PetscComplex& lhs, const Type& rhs) { return const_cast<PetscComplex&>(lhs).imag() == PetscReal(0) && const_cast<PetscComplex&>(lhs).real() == PetscReal(rhs); } \
57b6f7a5a8SLisandro Dalcin static inline bool operator==(const Type& lhs, const PetscComplex& rhs) { return const_cast<PetscComplex&>(rhs).imag() == PetscReal(0) && const_cast<PetscComplex&>(rhs).real() == PetscReal(lhs); } \
58b6f7a5a8SLisandro Dalcin static inline bool operator!=(const PetscComplex& lhs, const Type& rhs) { return const_cast<PetscComplex&>(lhs).imag() != PetscReal(0) || const_cast<PetscComplex&>(lhs).real() != PetscReal(rhs); } \
59b6f7a5a8SLisandro Dalcin static inline bool operator!=(const Type& lhs, const PetscComplex& rhs) { return const_cast<PetscComplex&>(rhs).imag() != PetscReal(0) || const_cast<PetscComplex&>(rhs).real() != PetscReal(lhs); } \
6039829747SLisandro Dalcin /* PETSC_CXX_COMPLEX_FIX */
6139829747SLisandro Dalcin 
62f636a84aSBarry Smith /*
63f636a84aSBarry Smith     Due to the C++ automatic promotion rules for floating point and integer values only the two cases below
64f636a84aSBarry Smith     need to be handled.
65f636a84aSBarry Smith */
6639829747SLisandro Dalcin #if defined(PETSC_USE_REAL_SINGLE)
6739829747SLisandro Dalcin PETSC_CXX_COMPLEX_FIX(double)
6839829747SLisandro Dalcin #elif defined(PETSC_USE_REAL_DOUBLE)
6939829747SLisandro Dalcin PETSC_CXX_COMPLEX_FIX(PetscInt)
7039829747SLisandro Dalcin #endif /* PETSC_USE_REAL_* */
7139829747SLisandro Dalcin 
7239829747SLisandro Dalcin #endif
73