xref: /petsc/include/petsccxxcomplexfix.h (revision 01f93aa2feb5cea225702f81765cbcdff6f6f7c0)
1 #pragma once
2 
3 /*
4     The pragma below silence all compiler warnings coming from code in this header file.
5     In particular, it silences `-Wfloat-equal` warnings in `operator==()` and `operator!=` below.
6     Other compilers beyond GCC support this pragma.
7 */
8 #if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__NEC__)
9   #pragma GCC system_header
10 #endif
11 
12 /*
13      Defines additional operator overloading for the C++ complex class that are "missing" in the standard
14      include files. For example, the code fragment
15 
16      std::complex<double> c = 22.0;
17      c = 11 + c;
18 
19      will produce a compile time error such as
20 
21      error: no match for 'operator+' (operand types are 'int' and 'std::complex<double>')
22 
23      The code fragment
24 
25      std::complex<float> c = 22.0;
26      c = 11.0 + c;
27 
28      will produce a compile time error such as
29 
30      error: no match for 'operator+' (operand types are 'double' and 'std::complex<float>')
31 
32      This deficiency means one may need to write cumbersome code while working with the C++ complex classes.
33 
34      This include file defines a few additional operator overload methods for the C++ complex classes to handle
35      these cases naturally within PETSc code.
36 
37      This file is included in petscsystypes.h when feasible. In the small number of cases where these additional methods
38      may conflict with other code one may add '#define PETSC_SKIP_CXX_COMPLEX_FIX 1' before including any PETSc include
39      files to prevent these methods from being provided.
40 */
41 
42 #define PETSC_CXX_COMPLEX_FIX(Type) \
43   static inline PetscComplex operator+(const PetscComplex &lhs, const Type &rhs) \
44   { \
45     return const_cast<PetscComplex &>(lhs) + PetscReal(rhs); \
46   } \
47   static inline PetscComplex operator+(const Type &lhs, const PetscComplex &rhs) \
48   { \
49     return PetscReal(lhs) + const_cast<PetscComplex &>(rhs); \
50   } \
51   static inline PetscComplex operator-(const PetscComplex &lhs, const Type &rhs) \
52   { \
53     return const_cast<PetscComplex &>(lhs) - PetscReal(rhs); \
54   } \
55   static inline PetscComplex operator-(const Type &lhs, const PetscComplex &rhs) \
56   { \
57     return PetscReal(lhs) - const_cast<PetscComplex &>(rhs); \
58   } \
59   static inline PetscComplex operator*(const PetscComplex &lhs, const Type &rhs) \
60   { \
61     return const_cast<PetscComplex &>(lhs) * PetscReal(rhs); \
62   } \
63   static inline PetscComplex operator*(const Type &lhs, const PetscComplex &rhs) \
64   { \
65     return PetscReal(lhs) * const_cast<PetscComplex &>(rhs); \
66   } \
67   static inline PetscComplex operator/(const PetscComplex &lhs, const Type &rhs) \
68   { \
69     return const_cast<PetscComplex &>(lhs) / PetscReal(rhs); \
70   } \
71   static inline PetscComplex operator/(const Type &lhs, const PetscComplex &rhs) \
72   { \
73     return PetscReal(lhs) / const_cast<PetscComplex &>(rhs); \
74   } \
75   static inline bool operator==(const PetscComplex &lhs, const Type &rhs) \
76   { \
77     return const_cast<PetscComplex &>(lhs).imag() == PetscReal(0) && const_cast<PetscComplex &>(lhs).real() == PetscReal(rhs); \
78   } \
79   static inline bool operator==(const Type &lhs, const PetscComplex &rhs) \
80   { \
81     return const_cast<PetscComplex &>(rhs).imag() == PetscReal(0) && const_cast<PetscComplex &>(rhs).real() == PetscReal(lhs); \
82   } \
83   static inline bool operator!=(const PetscComplex &lhs, const Type &rhs) \
84   { \
85     return const_cast<PetscComplex &>(lhs).imag() != PetscReal(0) || const_cast<PetscComplex &>(lhs).real() != PetscReal(rhs); \
86   } \
87   static inline bool operator!=(const Type &lhs, const PetscComplex &rhs) \
88   { \
89     return const_cast<PetscComplex &>(rhs).imag() != PetscReal(0) || const_cast<PetscComplex &>(rhs).real() != PetscReal(lhs); \
90   } \
91 /* PETSC_CXX_COMPLEX_FIX */
92 
93 /*
94     Due to the C++ automatic promotion rules for floating point and integer values only the two cases below
95     need to be handled.
96 */
97 #if defined(PETSC_USE_REAL_SINGLE)
98 PETSC_CXX_COMPLEX_FIX(double)
99 #elif defined(PETSC_USE_REAL_DOUBLE)
100 PETSC_CXX_COMPLEX_FIX(PetscInt)
101 #endif /* PETSC_USE_REAL_* */
102