xref: /petsc/include/petsccxxcomplexfix.h (revision 02c9f0b548ed2228330a66acd2df0a92dd2a8bb1)
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 /*
6f636a84aSBarry Smith      Defines additional operator overloading for the C++ complex class that are "missing" in the standard
7f636a84aSBarry Smith      include files. For example, the code fragment
8f636a84aSBarry Smith 
9f636a84aSBarry Smith      std::complex<double> c = 22.0;
10f636a84aSBarry Smith      c = 11 + c;
11f636a84aSBarry Smith 
12f636a84aSBarry Smith      will produce a compile time error such as
13f636a84aSBarry Smith 
14f636a84aSBarry Smith      error: no match for 'operator+' (operand types are 'int' and 'std::complex<double>')
15f636a84aSBarry Smith 
16f636a84aSBarry Smith      The code fragment
17f636a84aSBarry Smith 
18f636a84aSBarry Smith      std::complex<float> c = 22.0;
19f636a84aSBarry Smith      c = 11.0 + 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 'double' and 'std::complex<float>')
24f636a84aSBarry Smith 
25f636a84aSBarry Smith      This deficiency means one may need to write cumbersome code while working with the C++ complex classes.
26f636a84aSBarry Smith 
27f636a84aSBarry Smith      This include file defines a few additional operator overload methods for the C++ complex classes to handle
28f636a84aSBarry Smith      these cases naturally within PETSc code.
29f636a84aSBarry Smith 
30f636a84aSBarry Smith      This file is included automatically by PETSc include files. In the small number of cases where these additional methods
31f636a84aSBarry Smith      may conflict with other code one may add
32f636a84aSBarry Smith 
33f636a84aSBarry Smith      #define PETSC_SKIP_CXX_COMPLEX_FIX
34f636a84aSBarry Smith 
35f636a84aSBarry Smith      before including any PETSc include files to prevent these methods from being provided.
36f636a84aSBarry Smith */
37f636a84aSBarry Smith 
38*02c9f0b5SLisandro Dalcin #if defined(__GNUC__) && (__GNUC__ >= 4)
39*02c9f0b5SLisandro Dalcin #pragma GCC system_header
40*02c9f0b5SLisandro Dalcin #endif
41*02c9f0b5SLisandro Dalcin 
4239829747SLisandro Dalcin #define PETSC_CXX_COMPLEX_FIX(Type) \
43d4baf660SLisandro Dalcin static inline PetscComplex operator+(const PetscComplex& lhs, const Type& rhs) { return const_cast<PetscComplex&>(lhs) + PetscReal(rhs); } \
44d4baf660SLisandro Dalcin static inline PetscComplex operator+(const Type& lhs, const PetscComplex& rhs) { return PetscReal(lhs) + const_cast<PetscComplex&>(rhs); } \
45d4baf660SLisandro Dalcin static inline PetscComplex operator-(const PetscComplex& lhs, const Type& rhs) { return const_cast<PetscComplex&>(lhs) - PetscReal(rhs); } \
46d4baf660SLisandro Dalcin static inline PetscComplex operator-(const Type& lhs, const PetscComplex& rhs) { return PetscReal(lhs) - const_cast<PetscComplex&>(rhs); } \
47d4baf660SLisandro Dalcin static inline PetscComplex operator*(const PetscComplex& lhs, const Type& rhs) { return const_cast<PetscComplex&>(lhs) * PetscReal(rhs); } \
48d4baf660SLisandro Dalcin static inline PetscComplex operator*(const Type& lhs, const PetscComplex& rhs) { return PetscReal(lhs) * const_cast<PetscComplex&>(rhs); } \
49d4baf660SLisandro Dalcin static inline PetscComplex operator/(const PetscComplex& lhs, const Type& rhs) { return const_cast<PetscComplex&>(lhs) / PetscReal(rhs); } \
50d4baf660SLisandro Dalcin static inline PetscComplex operator/(const Type& lhs, const PetscComplex& rhs) { return PetscReal(lhs) / const_cast<PetscComplex&>(rhs); } \
51b6f7a5a8SLisandro 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); } \
52b6f7a5a8SLisandro 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); } \
53b6f7a5a8SLisandro 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); } \
54b6f7a5a8SLisandro 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); } \
5539829747SLisandro Dalcin /* PETSC_CXX_COMPLEX_FIX */
5639829747SLisandro Dalcin 
57f636a84aSBarry Smith /*
58f636a84aSBarry Smith     Due to the C++ automatic promotion rules for floating point and integer values only the two cases below
59f636a84aSBarry Smith     need to be handled.
60f636a84aSBarry Smith */
6139829747SLisandro Dalcin #if defined(PETSC_USE_REAL_SINGLE)
6239829747SLisandro Dalcin PETSC_CXX_COMPLEX_FIX(double)
6339829747SLisandro Dalcin #elif defined(PETSC_USE_REAL_DOUBLE)
6439829747SLisandro Dalcin PETSC_CXX_COMPLEX_FIX(PetscInt)
6539829747SLisandro Dalcin #endif /* PETSC_USE_REAL_* */
6639829747SLisandro Dalcin 
6739829747SLisandro Dalcin #endif /* __cplusplus && PETSC_HAVE_COMPLEX && PETSC_HAVE_CXX_COMPLEX */
6839829747SLisandro Dalcin #endif
69