xref: /petsc/include/petsccxxcomplexfix.h (revision 4cdc28b3da2add3050fcbd71344a6c6b9f13cd6a)
139829747SLisandro Dalcin #if !defined(PETSCCXXCOMPLEXFIX_H)
239829747SLisandro Dalcin #define PETSCCXXCOMPLEXFIX_H
339829747SLisandro Dalcin #if defined(__cplusplus) && defined(PETSC_HAVE_COMPLEX) && defined(PETSC_HAVE_CXX_COMPLEX)
439829747SLisandro Dalcin 
5f636a84aSBarry Smith /*
6*4cdc28b3SLisandro Dalcin     The pragma below silence all compiler warnings comming from code in this header file.
7*4cdc28b3SLisandro Dalcin     In particular, it silences `-Wfloat-equal` warnings in `operator==()` and `operator!=` below.
8*4cdc28b3SLisandro Dalcin     Other compilers beyond GCC support this pragma.
9*4cdc28b3SLisandro Dalcin */
10*4cdc28b3SLisandro Dalcin #if defined(__GNUC__) && (__GNUC__ >= 4)
11*4cdc28b3SLisandro Dalcin #pragma GCC system_header
12*4cdc28b3SLisandro Dalcin #endif
13*4cdc28b3SLisandro Dalcin 
14*4cdc28b3SLisandro Dalcin /*
15f636a84aSBarry Smith      Defines additional operator overloading for the C++ complex class that are "missing" in the standard
16f636a84aSBarry Smith      include files. For example, the code fragment
17f636a84aSBarry Smith 
18f636a84aSBarry Smith      std::complex<double> c = 22.0;
19f636a84aSBarry Smith      c = 11 + c;
20f636a84aSBarry Smith 
21f636a84aSBarry Smith      will produce a compile time error such as
22f636a84aSBarry Smith 
23f636a84aSBarry Smith      error: no match for 'operator+' (operand types are 'int' and 'std::complex<double>')
24f636a84aSBarry Smith 
25f636a84aSBarry Smith      The code fragment
26f636a84aSBarry Smith 
27f636a84aSBarry Smith      std::complex<float> c = 22.0;
28f636a84aSBarry Smith      c = 11.0 + c;
29f636a84aSBarry Smith 
30f636a84aSBarry Smith      will produce a compile time error such as
31f636a84aSBarry Smith 
32f636a84aSBarry Smith      error: no match for 'operator+' (operand types are 'double' and 'std::complex<float>')
33f636a84aSBarry Smith 
34f636a84aSBarry Smith      This deficiency means one may need to write cumbersome code while working with the C++ complex classes.
35f636a84aSBarry Smith 
36f636a84aSBarry Smith      This include file defines a few additional operator overload methods for the C++ complex classes to handle
37f636a84aSBarry Smith      these cases naturally within PETSc code.
38f636a84aSBarry Smith 
39f636a84aSBarry Smith      This file is included automatically by PETSc include files. In the small number of cases where these additional methods
40f636a84aSBarry Smith      may conflict with other code one may add
41f636a84aSBarry Smith 
42f636a84aSBarry Smith      #define PETSC_SKIP_CXX_COMPLEX_FIX
43f636a84aSBarry Smith 
44f636a84aSBarry Smith      before including any PETSc include files to prevent these methods from being provided.
45f636a84aSBarry Smith */
46f636a84aSBarry Smith 
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 /* __cplusplus && PETSC_HAVE_COMPLEX && PETSC_HAVE_CXX_COMPLEX */
7339829747SLisandro Dalcin #endif
74